2012-01-23 37 views
5

Tôi có một số đơn giản thiết lập cơ quan Box2D với một người biết lắng nghe tiếp xúc như vậy:Phát hiện va chạm ban đầu của hai cơ quan Box2D mà không cần liên tục va chạm

#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) { 

} 

Và tôi cần phải chơi một âm thanh khi hai cơ quan đã va chạm. Tuy nhiên, việc thực hiện này phát hiện va chạm liên tục nên âm thanh được phát khi các cơ quan chạm vào. Kiến thức của tôi về box2d và C++ đã rất hạn chế, có cách nào đơn giản để phát hiện một va chạm mới mà không phát hiện va chạm liên tục không?

+0

Tôi đề nghị bạn đi qua [hướng dẫn] (http://www.raywenderlich.com/606/how-to-use-box2d-for-just-collision-detection-with-cocos2d-iphone) để bạn sẽ có thể phát hiện va chạm đơn – Marine

+0

"Khi hai vật thể va chạm" = BeginContact. Đây không phải là một điều liên tục, đó là lý do tại sao nó được gọi là 'Bắt ​​đầu' :) – iforce2d

Trả lời

-1

Đầu tiên thiết lập một bộ đếm thời gian như thế này ..

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

và trong phương pháp này

- (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

Bạn có ý tưởng cơ bản đúng, nhưng nó cần một số sàng lọc.

Trong BeginContact (...) cuộc gọi của bạn, bạn có:

PLAYSOUND(COLLISION); 

Thay vì chơi âm thanh ở đây, những gì bạn cần làm là enqueue một số hệ thống khác để phát âm thanh cho cặp đặc biệt này. Đặt thẻ userdata của các vật thể của bạn thành con trỏ tới lớp (hoặc một số ID khác để theo dõi các thực thể). Cũng giống như vậy:

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()); 
     */ 
    } 
}; 

Phần cuối cùng của việc này là để KHÔNG chơi âm thanh một lần nữa trong một thời gian ngắn ngay cả khi một vụ va chạm xảy ra. Bạn có thể thực hiện việc này bằng cách tạo đồng hồ bấm giờ hoặc đếm ngược từ thời gian cố định trên các chu kỳ cập nhật đối tượng.

Điều này có hữu ích không?

Các vấn đề liên quan