如何在碰撞后删除Box2d中的对象,但是有延迟?

时间:2010-10-20 20:02:31

标签: iphone cocos2d-iphone box2d

我在iPhone游戏中使用cocos2d和box2d。

当两个球相互碰撞时,我通过ContactListener获得通知,并且我有两个实体的引用。

我可以摧毁它们,但我想延迟这样做。

所以,两个球相互撞击,它们反弹然后在第二个消失之后。

3 个答案:

答案 0 :(得分:0)

在BeginContact或EndContact中启动一个计时器,然后移除Body。

答案 1 :(得分:0)

答案 2 :(得分:0)

我使用类(下面)进行冲突处理,该类过滤掉重复冲突并通过邮件系统向“实体”对象发送通知。

注意:这是更大代码库的一部分;如果您需要澄清,请随时提出任何问题,因为代码不在此处。

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

一旦您的实体收到消息,每个实体都可以启动计时器并在需要时自行销毁。或者您可以让您的消息延迟排队,以便在游戏的消息处理阶段(如果有的话)销毁它们。这很好,因为它可以让你明确控制破坏发生的时间,并且在物理进行时不会发生破坏,这确实会导致引擎出现问题。