Objective c 如何使用cocos2d编写box2d联系人侦听器?

Objective c 如何使用cocos2d编写box2d联系人侦听器?,objective-c,cocos2d-iphone,box2d,Objective C,Cocos2d Iphone,Box2d,我一直在阅读关于如何编写联系人侦听器的各种教程,但我对此束手无策 以下是我到目前为止的情况: 在我代表一个物理对象的每个类中,我做: _body->SetUserData(self); 我编写了一个contact listener类,其中包含以下两种方法: void ContactListener::BeginContact(b2Contact* contact) { // Box2d objects that collided b2Fixture* fixtureA =

我一直在阅读关于如何编写联系人侦听器的各种教程,但我对此束手无策

以下是我到目前为止的情况: 在我代表一个物理对象的每个类中,我做:

_body->SetUserData(self);
我编写了一个contact listener类,其中包含以下两种方法:

void ContactListener::BeginContact(b2Contact* contact)
{
    // Box2d objects that collided
    b2Fixture* fixtureA = contact->GetFixtureA();
    b2Fixture* fixtureB = contact->GetFixtureB();
    // Sprites that collided
    MyNode* actorA = (MyNode*) fixtureA->GetBody()->GetUserData();
    MyNode* actorB = (MyNode*)  fixtureB->GetBody()->GetUserData();
}

void ContactListener::EndContact(b2Contact* contact)
{
    // Box2d objects that collided
    b2Fixture* fixtureA = contact->GetFixtureA();
    b2Fixture* fixtureB = contact->GetFixtureB();
    // Sprites that collided
    MyNode* actorA = (MyNode*) fixtureA->GetBody()->GetUserData();
    MyNode* actorB = (MyNode*)  fixtureB->GetBody()->GetUserData();
}
我不知道下一步该怎么办。我现在有两个正在碰撞的精灵,但我想做以下事情: 1) 当它们碰撞时,我想根据对象的类型从世界上移除一个精灵。(例如,如果一个是cat对象,另一个是鼠标对象,我想删除鼠标对象

2) 我想让猫知道它吃了一只老鼠

3) 我希望猫继续移动,就好像它没有接触到鼠标一样

4) 我仍然不想让这只猫正常地与地形之类的东西相撞

我下一步做什么?我不知道该怎么办?如何让猫继续正常地与地形碰撞,而不是与鼠标碰撞?何时移除鼠标?

拥有一个“实体”类来保存对Box2D主体的引用并对其进行操作,这绝对是一个好方法。如果你有一个宇宙飞船类和一个流星类,它们中的每一个都可以提供它们自己的控制身体(AI)的派生方法,但是它们都有共同的逻辑和代码来支持对“有身体的东西”的操作(例如共同的“实体”基类)。我认为你在正确的轨道上

当接触开始发生时,它变得有点模糊。这是您开始进入整个系统的架构的地方,而不仅仅是物理世界的结构或单个Coco2d场景

以下是我过去是如何做到这一点的:

首先,我设置了联系人侦听器,如下所示:

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)
   {
      b2Fixture* fixtureA = contact->GetFixtureA();
      b2Body* bodyA = fixtureA->GetBody();
      Entity* entityA = bodyA->GetUserData();
      b2Fixture* fixtureB = contact->GetFixtureB();
      b2Body* bodyB = fixtureB->GetBody();
      Entity* entityB = bodyB->GetUserData();

      if(test if entityA and entityB should not have collision response)
      {
         contact->SetEnabled(false);
      }
      // Do this if you want there to be collision notification, even if
      // there is no response.
      AddContactPair(entA,entB);
   }

   void AddContactPair(Entity* entA, Entity* entB)
   {
      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 BeginContact(b2Contact* contact)
   {
      Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData();
      Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData();

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

      // Not sure this is still needed if you add it in the pre-solve.
      // May not be necessary...
      AddContactPair(entA, entB);
   }

   // BEWARE:  You may get multiple calls for the same event.
   void EndContact(b2Contact* contact)
   {
   }
};
类EntityContactListener:公共ContactListener
{
私人:
游戏世界*\u游戏世界;
EntityContactListener(){}
类型定义结构
{
实体*entA;
实体*entB;
}接触线对;
矢量接触对;
公众:
虚拟~EntityContactListener(){}
EntityContactListener(游戏世界*游戏世界):
_游戏世界(gameWorld)
{
_触点对。保留(128);
}
void
{
讯息*msg;
MessageManager&mm=GameManager::Instance().GetMessageMgr();
对于(uint32 idx=0;idx<_contactPairs.size();idx++)
{
实体*entA=_contactPairs[idx].entA;
实体*entB=_contactPairs[idx].entB;
//DebugLogCPP(“联系通知%s%s”,entA->ToString().c_str(),entB->ToString().c_str());
msg=mm.CreateMessage();
msg->Init(entA->GetID(),entB->GetID(),Message::Message\u冲突);
mm.排队消息(msg,0);
msg=mm.CreateMessage();
msg->Init(entB->GetID(),entA->GetID(),Message::Message\u冲突);
mm.排队消息(msg,0);
}
_contactPairs.clear();
}
无效预溶解(b2Contact*contact,常数b2Manifold*oldManifold)
{
b2Fixture*fixtureA=contact->GetFixtureA();
b2Body*bodyA=fixtureA->GetBody();
实体*entityA=bodyA->GetUserData();
b2Fixture*fixtureB=contact->GetFixtureB();
b2Body*bodyB=fixtureB->GetBody();
实体*entityB=bodyB->GetUserData();
if(测试entityA和entityB是否不应具有冲突响应)
{
联系人->设置启用(错误);
}
//如果希望有冲突通知,请执行此操作,即使
//没有回应。
添加触点对(entA、entB);
}
void AddContactPair(实体*entA,实体*entB)
{
对于(uint32 idx=0;idx<_contactPairs.size();idx++)
{
if(_contactPairs[idx].entA==entA&&u contactPairs[idx].entB==entB)
回来
//不确定是否需要这个。。。
if(_contactPairs[idx].entA==entB&&u contactPairs[idx].entA==entB)
回来
}
接触线对;
pair.entA=entA;
pair.entB=entB;
_触点对。推回(对);
}
//注意:同一事件可能会有多个呼叫。
无效BeginContact(b2Contact*contact)
{
实体*entA=(实体*)联系人->GetFixtureA()->GetBody()->GetUserData();
实体*entB=(实体*)联系人->GetFixtureB()->GetBody()->GetUserData();
断言(entA!=NULL);
断言(entB!=NULL);
//如果将其添加到预解算中,则不确定是否仍需要此项。
//可能没有必要。。。
添加触点对(entA、entB);
}
//注意:同一事件可能会有多个呼叫。
无效结束触点(b2Contact*触点)
{
}
};
由于引擎的工作方式,你可以得到多个相同的机构接触点击。此侦听器对它们进行过滤,因此如果两个实体发生冲突,您只会收到一条消息

侦听器仅存储发生的冲突。为了其他目的,可以对其进行修改,将其进一步分为“开始”和“结束”。在这里,“接触”的意思是“你被什么东西击中了”。我不需要知道它是否停止了联系

这就是所谓的“秘密酱汁”。它向两个联系的实体(通过消息系统)发送一条消息,表明他们击中了某个对象,而另一个实体就是他们击中的对象。子弹击中了船。子弹毁灭自我。基于子弹属性(getDamageIncomputed()方法)进行自我伤害。这进而向图形系统发出信号,要求将项目符号从显示屏上移除。如果船被毁了,它也会被毁

从整体执行的角度来看: 开始之前,请指定联系人侦听器

游戏的每个周期: 对所有实体调用“更新”。这更新了他们的物理力等。 更新Box2d世界。 在侦听器上调用notify。 从系统中删除死实体


这有用吗?

我还是迷路。我有3个实体-猫,老鼠,地形。猫鼠手