Как я могу удалить объекты в Box2d после столкновения, но с задержкой? - PullRequest
0 голосов
/ 21 октября 2010

Я использую cocos2d и box2d в моей игре для iPhone.

Когда два шара ударяются друг о друга, я получаю уведомление, хотя ContactListener и у меня есть ссылка на оба тела.

Я могу уничтожить их обоих, но я бы хотел сделать это с задержкой.

Итак, два шара ударяются друг о друга, отскакивают, а затем через секунду исчезают.

Ответы [ 3 ]

0 голосов
/ 05 мая 2011

это идеальный пример для вашей проблемы

http://www.raywenderlich.com/505/how-to-create-a-simple-breakout-game-with-box2d-and-cocos2d-tutorial-part-22

0 голосов
/ 10 ноября 2013

Я выполняю обработку столкновений, используя класс (ниже), который отфильтровывает повторяющиеся столкновения и отправляет уведомления объектам «Entity» через систему обмена сообщениями.

ПРИМЕЧАНИЕ. Это часть большой кодовой базы;не стесняйтесь задавать любые вопросы, если вам нужны разъяснения, потому что кода здесь нет.

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

Как только ваши сущности получают сообщение, каждый может запустить таймер и уничтожить себя при необходимости.Или вы можете поставить свои сообщения в очередь с задержкой, чтобы они были уничтожены на этапе обработки сообщений в вашей игре (если он у вас есть).Это хорошо, потому что дает вам явный контроль над тем, когда происходит разрушение, и не позволяет ему произойти, пока идет физика, что может вызвать проблемы с двигателем.

0 голосов
/ 26 октября 2010

Запустите таймер в BeginContact или EndContact и затем удалите тело.

...