0

iPhone ゲームで cocos2d と box2d を使用しています。

2 つのボールが互いに衝突すると、ContactListener を介して通知を受け取り、両方のボディへの参照を取得します。

両方とも破壊できますが、遅らせてやりたいと思います。

そのため、2 つのボールが互いに衝突し、跳ね返り、1 秒後に消えます。

4

3 に答える 3

0

これはあなたの問題に最適なデモです

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

于 2011-05-05T05:48:34.707 に答える
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());
       */
   }
};

エンティティがメッセージを受信すると、それぞれがタイマーを開始し、必要に応じて自身を破棄できます。または、ゲームのメッセージ処理フェーズ中にメッセージが破棄されるように、メッセージを遅延してエンキューすることもできます (ある場合)。これは、破壊がいつ発生するかを明示的に制御できるため、物理現象が進行している間は破壊が発生しないため、エンジンに実際に問題を引き起こす可能性があるため、優れています。

于 2013-11-10T11:52:51.477 に答える
0

BeginContact または EndContact でタイマーを開始し、Body を削除します。

于 2010-10-25T21:23:11.810 に答える