天天看點

cocos2d-x-3.3-021-碰撞檢測3-實體引擎碰撞過濾 引子 PhysicsBody相關API說明 DEMO及源碼 驗證對API的了解 總結

原文同步釋出于我的wiki,檢視原文或更新請移步: 點選打開連結

引子

  • 上一篇簡單示範了如何使用實體引擎以及用它來作碰撞監測。但有問題,那就是敵人和敵人也會發生碰撞,子彈和子彈之間也會發生碰撞。。。要解決這個問題(避免不必要的碰撞,或碰撞過濾),得先看看cocos封裝實體引擎後給我們提供的API。

PhysicsBody相關API說明

  • void setGroup(int group);
Collision groups let you specify an integral group index. 
You can have all fixtures with the same group index always collide 
(positive index) or never collide (negative index)
      it have high priority than bit masks


PhysicsBody的Group
1.優先級比bit masks的優先級高(CategoryBitmask,ContactTestBitmask,CollisionBitmask)
2.group是正數且相等的話,就一定碰撞
3.group是負數且相等的話,就一定不會碰撞
4.group其他情況沒說,應該是取決于bit masks了
           
  • void setCategoryBitmask(int bitmask);
A mask that defines which categories this physics body belongs to.
      Every physics body in a scene can be assigned to up to 32 
different categories, each corresponding to a bit in the bit mask. 
You define the mask values used in your game. 
In conjunction with the collisionBitMask and contactTestBitMask properties, 
you define which physics bodies interact with each other 
and when your game is notified of these interactions.
      The default value is 0xFFFFFFFF (all bits set).


PhysicsBody的CategoryBitmask
1.CategoryBitmask用來标記這個PhysicsBody的所屬類别
2.每個PhysicsBody最多可以屬于32個類别,一個bit代表一個類别,0代表不是對應類别,1代表是對應類别
3.和另外兩個屬性(collisionBitMask and contactTestBitMask)配合着用
4.預設值0xFFFFFFFF,即這個PhysicsBody分别屬于所有的32個類别
           
  • void setContactTestBitmask(int bitmask);
A mask that defines which categories of bodies cause intersection 
notifications with this physics body.
      When two bodies share the same space, each body’s category mask is 
tested against the other body’s contact mask by performing a logical
 AND operation. If either comparison results in a non-zero value, 
an PhysicsContact object is created and passed to the physics 
world’s delegate. For best performance, only set bits in the 
contacts mask for interactions you are interested in.
      The default value is 0x00000000 (all bits cleared).


PhysicsBody的ContactTestBitmask
1.ContactTestBitmask用來定義哪個類别的PhysicsBody可以和這個PhysicsBody産生相交通知
2.舉個例子:有PhysicsBody A B占了同樣的空間了。如何判斷A B要産生相交通知呢,
if((A.CategoryBitmask & B.ContactTestBitmask) != 0 || (A.ContactTestBitmask & B.CategoryBitmask) != 0)
    {/*條件成立,執行相交通知*/}
else{/*沒有相交通知*/}
3.為了性能考慮,相交通知隻應該設定給我們感興趣的物體
4.預設值0x00000000 (all bits cleared),沒有哪個類别的PhysicsBody可以産生相交通知
           
  • void setCollisionBitmask(int bitmask);
A mask that defines which categories of physics bodies 
can collide with this physics body.
      When two physics bodies contact each other, a collision may occur. 
This body’s collision mask is compared to the other body’s category 
mask by performing a logical AND operation. If the result is a 
non-zero value, then this body is affected by the collision. 
Each body independently chooses whether it wants to be affected 
by the other body. For example, you might use this to avoid collision 
calculations that would make negligible changes to a body’s velocity.
      The default value is 0xFFFFFFFF (all bits set).


PhysicsBody的CollisionBitmask
1.CollisionBitmask是用來定義哪個類别的PhysicsBody可以和這個PhysicsBody産生碰撞
2.舉個例子:有PhysicsBody A B彼此接觸了,那碰撞就可能發生。
A受不受這個碰撞的影響(展現為實體效果)表達為:
if((A.CollisionBitmask & B.CategoryBitmask) != 0 ){/*A産生碰撞的實體效果*/} 
else{/*A沒效果*/}
3.至于B受不受這個碰撞的影響,則采用同樣的表達式單獨計算即可
if((B.CollisionBitmask & A.CategoryBitmask) != 0 ){/*B産生碰撞的實體效果*/} 
else{/*B沒效果*/}
4.預設值0xFFFFFFFF (all bits set),所有類别的PhysicsBody都能對this body産生碰撞效果
           

DEMO及源碼

  • 基于cocos 3.4final
  • DEMO功能:注冊了實體碰撞事件的監聽,用來檢視是否有事件回調;注冊了touch事件監聽,在touch的結束事件裡回在觸摸點建立一個帶實體效果的精靈。精靈有兩種,用來測試PhysicsBody的設定造成的影響。具體看代碼,不複雜。
  • https://github.com/cheyiliu/CollisionDetection

驗證對API的了解

所有參數保持預設

屬性值:
group             =0
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000000
CollisionBitmask  =0xFFFFFFFF

           
  • 現象和分析:
    1. a b為同一類物品,有碰撞現象【group未設定; 那就套上面的API的分析,

      (a.CategoryBitmask & b.CollisionBitmask) != 0

       true; 反過來也是; 故a b都有碰撞效果。】
    2. a b為同一類物品,無碰撞回調【套公式 

      ((a.CategoryBitmask & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)

      等于false,故沒回調。】

确認group優先級

屬性值:
group             =需要設定<-----
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000000
CollisionBitmask  =0xFFFFFFFF

           
  • 現象和分析:
    1. a b為同一類物品,group都取1。有碰撞現象,無回調【跟group不設定時現象一樣,還不能說明什麼】
    2. a b為同一類物品,group都取-1。無碰撞現象,無回調,物體a b分别從同一個位置落下後,a b重疊【其他bitmask的預設值設定是有碰撞現象的,但設定group取相同的負數後沒碰撞了,group優先級高!】
    3. a b為同一類物品,group都取1,但設定CollisionBitmask=0x00(試圖不要碰撞效果)。現象1自由落體到世界外面去了,現象2快速touch在同一個位置産生兩個精靈會有擠開的現象(若group取-1則不會擠開,疊在一起了)。【說明group的優先級最高!】
    4. a b為同一類物品,group都取1,但設定CollisionBitmask=0x00(試圖不要碰撞效果),設定ContactTestBitmask=0x01(試圖擷取回調)。現象1自由落體到世界外面去了;現象2快速touch在同一個位置産生兩個精靈會有擠開的現象(若group取-1則不會擠開,疊在一起了);現象3有回調。【說明group的優先級最高!】

想要回調

屬性值:
group             =0
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000001<-----change to this
CollisionBitmask  =0xFFFFFFFF

           
  • 現象和分析:
    1. a b為同一類物品,有碰撞現象,有回調【碰撞的理由是

      (a.CollisionBitmask & b.CategoryBitmask) != 0

      非0, true;有回調的理由是

      ((a.CategoryBitmask & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)

       等于true】

想要回調但不要碰撞效果

屬性值:
group             =0
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000001<-----change to this
CollisionBitmask  =0x00000000<-----change to this

           
  • 現象和分析:
    1. a b為同一類物品,無碰撞現象,無回調【不碰撞的理由是

      (a.CollisionBitmask & b.CategoryBitmask) != 0

       等于0,false,;無回調的理由是雖然

      ((a.CategoryBitmask & b.ContactTestBitmask) != 0|| (a.ContactTestBitmask & b.CategoryBitmask) != 0)

       等于true,但是沒有碰撞的前提】

想要A類和B類碰撞,A類之間不碰撞,B類之間不碰撞-法1

屬性值:
group             =0【A的group取-1;B的group取-2】
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0xFFFFFFFF【AB都取這個值】
CollisionBitmask  =0xFFFFFFFF

           
  • 現象和分析:
    1. 同類之間不碰撞,a b為同一類物品【group決定的,相同的負的group值的對象不會碰撞;雖然

      ((a.CategoryBitmask & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)

      等于true,但沒碰撞的前提,故無回調】
    2. 不同類可以碰撞,a b為不同類的物品【group的值不一樣,取決于bitmask了;碰撞的理由是

      (a.CollisionBitmask & b.CategoryBitmask) != 0

      非0,true,b也是;回調理由是有碰撞且

      ((a.CategoryBitmask & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)

       等于true】

想要A類和B類碰撞,A類之間不碰撞,B類之間不碰撞-法2

屬性值:
group             =0【AB都保持預設0】
CategoryBitmask   =【A的CategoryBitmask=0x01;B的CategoryBitmask=0x02】
ContactTestBitmask=【A的ContactTestBitmask=0x02;B的ContactTestBitmask=0x01】
CollisionBitmask  =【A的CollisionBitmask=0x02;B的CollisionBitmask=0x01】

           
  • 現象和分析:
    1. 同類之間無碰撞,a b為同一類物品【無碰撞的理由是

      (a.CollisionBitmask & b.CategoryBitmask) != 0

      false; 無回調是

      ((a.CategoryBitmask & b.CollisionBitmask) != 0 || (a.CollisionBitmask & b.CategoryBitmask) != 0)

      等于false故無回調】
    2. 不同類可以碰撞,a b為不同類的物品【碰撞的理由是

      (a.CollisionBitmask & b.CategoryBitmask) != 0

      true,b也是;回調理由是有碰撞且

      ((a.CategoryBitmask & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)

      等于true】

效果圖

  • 想要A類和B類碰撞,A類之間不碰撞,B類之間不碰撞(NOTE: gif中,相同的圖檔是同一類,不同圖檔類型不同) 
  • https://github.com/cheyiliu/All-in-One/raw/master/res/cocos2d/CollisionDetection-way3-use-physics-engine-filter.gif

總結

  • 能碰撞,不能碰撞以及碰撞事件通知的大緻邏輯
PhysicsBody a;
PhysicsBody b;

if ((a.group == b.group) && a.group > 0) {
    /*能碰撞,有碰撞的實體效果*/
    if (((a.CategoryBitmask & b.ContactTestBitmask) != 0)
            || ((a.ContactTestBitmask & b.CategoryBitmask) != 0)) {
        /*條件成立,執行相交通知*/
    }
} else if ((a.group == b.group) && a.group < 0) {
    /*不能碰撞,沒有碰撞的實體效果*/
} else {
    if ((a.CollisionBitmask & b.CategoryBitmask) != 0) {
        /*a能碰撞,a有碰撞的實體效果*/
        if (((a.CategoryBitmask & b.ContactTestBitmask) != 0)
                || ((a.ContactTestBitmask & b.CategoryBitmask) != 0)) {
            /*條件成立,執行相交通知*/
        }
    } else {
        /*a不能碰撞,a沒有碰撞的實體效果*/
    }

    if ((b.CollisionBitmask & a.CategoryBitmask) != 0) {
        /*b能碰撞,b有碰撞的實體效果*/
        if (((a.CategoryBitmask & b.ContactTestBitmask) != 0)
                || ((a.ContactTestBitmask & b.CategoryBitmask) != 0)) {
            /*條件成立,執行相交通知*/
        }
    } else {
        /*b不能碰撞,b沒有碰撞的實體效果*/
    }

}
           

繼續閱讀