2012-01-23 70 views
5

我有一些簡單的Box2D的機構設置與接觸監聽器,如下:檢測兩個Box2D的機構的初始碰撞沒有連續碰撞

#import "MyContactListener.h" 

MyContactListener::MyContactListener() : _contacts() { 
} 

MyContactListener::~MyContactListener() { 
} 

void MyContactListener::BeginContact(b2Contact* contact) { 
// We need to copy out the data because the b2Contact passed in 
// is reused. 
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() }; 
_contacts.push_back(myContact); 


b2Body *A = contact->GetFixtureA()->GetBody(); 
b2Body *B = contact->GetFixtureA()->GetBody(); 

NSLog(@"Collision detected!"); 
PLAYSOUND(COLLISION); 

} 

void MyContactListener::EndContact(b2Contact* contact) { 
    MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() }; 
    std::vector<MyContact>::iterator pos; 
    pos = std::find(_contacts.begin(), _contacts.end(), myContact); 
    if (pos != _contacts.end()) { 
     _contacts.erase(pos); 
     } 
} 

void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) { 

} 

void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) { 

} 

,我需要播放聲音時,兩具屍體已經碰撞。然而,這種實現檢測連續的碰撞,因此當身體接觸時播放聲音。我對box2d和C++的瞭解已經非常有限,是否有一種簡單的方法來檢測新的碰撞而不會檢測到連續的碰撞?

+0

我建議你通過[教程]去(http://www.raywenderlich.com/606/how-to-use-box2d-for-just-collision-detection-with-cocos2d-iphone),這樣你將能夠檢測到單個碰撞 – Marine

+0

「兩個物體碰撞時」= BeginContact。這不是一個連續的事情,這就是爲什麼它被稱爲'開始':) – iforce2d

回答

-1

首先設置一個計時器,這樣的..

[self schedule:@selector(check collision:)]; 

並在此方法

- (void)tick:(ccTime) dt 
    { 

     for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) 
      { 
      //--------------My contact Listener Start------------------------- 


       std::vector<MyContact>::iterator pos; 

       for(pos = _contactListener->_contacts.begin(); pos != _contactListener->_contacts.end(); ++pos) 
        { 
         MyContact contact = *pos; 

      // Here get your sprite and make their fixture and check... 

         if ((contact.fixtureA == tempballFixture && contact.fixtureB == _mainballFixture) || 
          (contact.fixtureA == _mainballFixture && contact.fixtureB == tempballFixture)) 
         { 
          if(mainDelegate.music_playing == TRUE) 
          { 
          [[SimpleAudioEngine sharedEngine] playEffect:@"Rock impact.mp3"]; 
          } 
          //-------------collision count for update score value-------- 
        } 
      } 
0

你有正確的基本理念,但它需要一些細化。

在你BeginContact(...)調用,您可以:

PLAYSOUND(COLLISION); 

而不是在這裏玩的聲音,你應該做的是排隊一些其他系統播放聲音爲這個特殊的對。將你的body的userdata標籤設置爲指向該類的指針(或其他一些ID以跟蹤實體)。像這樣:

class EntityContactListener : public ContactListener 
{ 
private: 
    GameWorld* _gameWorld; 
    EntityContactListener() {} 

    typedef struct 
    { 
     Entity* entA; 
     Entity* entB; 
    } CONTACT_PAIR_T; 

    vector<CONTACT_PAIR_T> _contactPairs; 

public: 
    virtual ~EntityContactListener() {} 

    EntityContactListener(GameWorld* gameWorld) : 
     _gameWorld(gameWorld) 
    { 
     _contactPairs.reserve(128); 
    } 

    void NotifyCollisions() 
    { 
     Message* msg; 
     MessageManager& mm = GameManager::Instance().GetMessageMgr(); 

     for(uint32 idx = 0; idx < _contactPairs.size(); idx++) 
     { 
     Entity* entA = _contactPairs[idx].entA; 
     Entity* entB = _contactPairs[idx].entB; 

     //DebugLogCPP("Contact Notification %s<->%s",entA->ToString().c_str(),entB->ToString().c_str()); 

     msg = mm.CreateMessage(); 
     msg->Init(entA->GetID(), entB->GetID(), Message::MESSAGE_COLLISION); 
     mm.EnqueueMessge(msg, 0); 

     msg = mm.CreateMessage(); 
     msg->Init(entB->GetID(), entA->GetID(), Message::MESSAGE_COLLISION); 
     mm.EnqueueMessge(msg, 0);   
     } 
     _contactPairs.clear(); 
    } 

    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) 
    { 

    } 

    // BEWARE: You may get multiple calls for the same event. 
    void BeginContact(b2Contact* contact) 
    { 
     Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData(); 
     Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData(); 
     //DebugLogCPP("Begin Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str()); 
     if(entA->GetGroupID() == entB->GetGroupID()) 
     { // Can't collide if they are in the same group. 
     return; 
     } 

     assert(entA != NULL); 
     assert(entB != NULL); 

     for(uint32 idx = 0; idx < _contactPairs.size(); idx++) 
     { 
     if(_contactPairs[idx].entA == entA && _contactPairs[idx].entB == entB) 
      return; 
     // Not sure if this is needed... 
     if(_contactPairs[idx].entA == entB && _contactPairs[idx].entA == entB) 
      return; 
     } 
     CONTACT_PAIR_T pair; 
     pair.entA = entA; 
     pair.entB = entB; 
     _contactPairs.push_back(pair); 
    } 

    // BEWARE: You may get multiple calls for the same event. 
    void EndContact(b2Contact* contact) 
    { 
     /* 
     Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData(); 
     Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData(); 
     DebugLogCPP("End Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str()); 
     */ 
    } 
}; 

的這最後一部分是再次播放聲音,即使發生碰撞的時間很短。您可以通過創建秒錶或從實體更新週期的固定時間開始倒計時來完成此操作。

對您有幫助嗎?