LevelHelper Cocos2d-x with Box2d(二)處理碰撞事件

 1、在各種不同類型的精靈之間註冊碰撞

考慮到你的遊戲中擁有各種不同類型的精靈,但有時候我們只關心其中某兩種類型之間的碰撞。

例如在超級瑪麗中,馬里奧(Mario)和關卡中的硬幣、站點(CheckPoint,不知道咋翻譯)、烏龜之間的碰撞。在這種情況下,讓我們先來定義碰撞的回調函數吧。

你可以同時定義碰撞前後的回調函數,也可以只定義碰撞前,或者碰撞後。具體得按你遊戲中需求來做,代碼如下

  1. void HelloWorld::preCollisionBetweenMarioAndCoin(LHContactInfo* contact) 
  2.     CCLog("PRE Mario ... Coin"); 
  3. void HelloWorld::preCollisionBetweenMarioAndTurtle(LHContactInfo* contact)
  4.     CCLog("Mario ... Turtle"); 
  5. void HelloWorld::preCollisionBetweenMarioAndCheckpoint(LHContactInfo* contact)
  6.     CCLog(@"Mario ... Checkpoint"); 
  7. void HelloWorld::postCollisionBetweenMarioAndCoin(LHContactInfo* contact)
  8.     CCLog(@"Mario ... Coin"); 
  9. void HelloWorld::postCollisionBetweenMarioAndTurtle(LHContactInfo* contact)
  10.     CCLog(@"Mario ... Turtle"); 
  11. void HelloWorld::postCollisionBetweenMarioAndCheckpoint(LHContactInfo* contact)
  12.     CCLog(@"Mario ... Checkpoint"); 

現在定義好了我們所需要的函數,接下來就只要讓LevelHelper在碰撞發生的時候去調用它們就行了。首先在我們載入關卡的後面寫上以下方法:

  1. //creating the objects 
  2. loader->addObjectsToWorld(world, this); 
  3.  
  4. ...                 
  5.          
  6. loader->useLevelHelperCollisionHandling();//這個方法是必要的,否則碰撞將不會執行 
  7.  
  8. loader->registerPreColisionCallbackBetweenTagA(COIN, MARIO, this
  9.     callfuncO_selector(HelloWorld::preCollisionBetweenMarioAndCoin)) 
  10.  
  11. loader->registerPostColisionCallbackBetweenTagA(COIN, MARIO, this
  12.     callfuncO_selector(HelloWorld::postCollisionBetweenMarioAndCoin)) 
  13.  
  14. loader->registerPreColisionCallbackBetweenTagA(CHECKPOINT, MARIO, this
  15.     callfuncO_selector(HelloWorld::preCollisionBetweenMarioAndCheckpoint)) 
  16.  
  17. loader->registerPostColisionCallbackBetweenTagA(CHECKPOINT, MARIO, this
  18.     callfuncO_selector(HelloWorld::postCollisionBetweenMarioAndCheckpoint)) 
  19.  
  20. loader->registerPreColisionCallbackBetweenTagA(TURTLE, MARIO, this
  21.     callfuncO_selector(HelloWorld::preCollisionBetweenMarioAndTurtle)) 
  22.  
  23. loader->registerPostColisionCallbackBetweenTagA(TURTLE, MARIO, this
  24.     callfuncO_selector(HelloWorld::postCollisionBetweenMarioAndTurtle)) 

在碰撞事件的函數中,會發現有一個參數LHContactInfo* contact,它將返回所有發生碰撞時的信息。

爲了獲得碰撞的兩個物體,可以很簡單的通過contact來獲得:

  1. void HelloWorld::preCollisionBetweenMarioAndCoin(LHContactInfo* contact) 
  2.     CCLog("Mario ... Coin"); 
  3.     b2Body* coin = contact->bodyA; 
  4.     b2Body* mario= contact->bodyB;     

更多可用的信息都在LHContactInfo這個類中,詳細可以查看具體的源碼。下面我簡單描述部分屬性:

  1. // 獲得 TagA/TagB 屬性對應的body 
  2. b2Body* bodyA = contact->bodyA; 
  3. b2Body* bodyB = contact->bodyB;  
  4.  
  5. // 獲得 TagA/TagB 屬性對應的精靈對象,  
  6. // 如果發生碰撞的是貝塞爾曲線/直線, 則返回NULL, 所以使用之前需要覈查是否爲空 
  7. LHSprite* sprA = contact->spriteA();  
  8. LHSprite* sprB = contact->spriteB();   
  9.  
  10. // Box2d contact info, 可以查看源碼獲得它更多的信息 
  11. b2Contact* boxContact = contact->contact;  
  12.  
  13. // old manifold info, 只在pre Collision有效 
  14. // 如果發生碰撞的body具有Sensor屬性, 則返回NULL,使用之前需檢查 
  15. const b2Manifold* oldManifold = contact->oldManifold;  
  16.  
  17. // 碰撞發生時的衝量信息, 只在post Collision有效 
  18. // 如果發生碰撞的body具有Sensor屬性, 則返回NULL,使用之前需檢查 
  19. const b2ContactImpulse* impulse = contact->impulse;  

 

2、靜態物體與靜態物體, 或者手動移動靜態物體與其他類型的物體發生碰撞

在Box2D中,會將靜態物體的質量存儲爲零,靜態物體可以讓用戶手動移動,它速度爲零。另外它不會和其他任意類型的物體相互碰撞。

但有時候我們需要檢測到靜態物體間的相互碰撞。那該怎麼做呢?

想象你有一個臺階(platform靜態)通過LevelHelper的路徑動畫上下來回移動;

想象你需要有一個在臺階與玩家之間碰撞發生時的回調函數。

這時,像剛纔那樣定義的回調函數是不會執行的。

 

解決方法:

*複製一份platform, 並在LevelHelper中設置爲不可見。

*設置新的這個platform屬性爲:  "Is Sensor", "Dynamic", "Is Bullet", "Fixed Rotation",

*設置新的platform tag 與之前的匹配,

*通過距離關節把這兩個platform綁定在一塊。

現在兩個物體就會同時運動,但在遊戲中我們看不到新的這個platform,因爲它是不可見的。但它卻能幫你檢測碰撞。幫你處理其他更多的邏輯信息。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章