在Box2D中获取世界的contactListener

时间:2012-06-02 23:29:06

标签: objective-c macos cocos2d-iphone box2d objective-c++

我正在使用cocos2D和Box2D为Mac OS编写游戏。我在我的世界中添加了一个b2ContactListener子类,如下所示:

contactListener = new ContactListener();
world->SetContactListener(contactListener);

这很有效,但我不确定从其他目前没有直接引用联系人监听器的类访问联系人监听器的最佳/可接受方式。

我知道我可以将引用传递给需要它的其他类,但我想知道的是否有更好的方法。更具体地说,虽然我找不到这样做的方法,但是有一些相当的:

world->GetContactListener();
Box2D中的

我试图这样做的原因仅仅是因为我更愿意将一些游戏逻辑(即一个身体是否能够根据来自联系人听众的信息跳转)移动到相关的类本身,而不是将所有内容都放入主要的游戏类。

谢谢!

2 个答案:

答案 0 :(得分:3)

联系人侦听器只是作为BeginContact,EndContact,PreSolve和PostSolve四个函数的入口点。通常它没有成员变量,因此没有理由得到它,因为没有任何东西可以从中获取。

当在世界步骤中调用其中一个功能时,您可以记录触摸/停止触摸的两个内容等,但是您不应该立即更改世界上的任何内容,直到时间步骤完成。

我认为这个问题的关键是用来“记录”哪些内容触及的方法,但这取决于你需要什么样的信息。例如,如果你只对BeginContact感兴趣,那么绝对最简单的方法就是将两个灯具作为一对列表进行存储:

std::vector< std::pair<b2Fixture*, b2Fixture*> > thingsThatTouched;

//in BeginContact
thingsThatTouched.push_back( make_pair(contact->GetFixtureA(), contact->GetFixtureB()) );

//after the time step
for (int i = 0; i < thingsThatTouched.size(); i++) {
    b2Fixture* fixtureA = thingsThatTouched[i].first;
    b2Fixture* fixtureB = thingsThatTouched[i].second;
    // ... do something clever ...
}
thingsThatTouched.clear(); //important!!

为了实现这一点,您需要通过联系人侦听器函数使thingThatTouched列表可见,因此它可以是全局变量,也可以在联系人侦听器类中设置指向它的指针,或者可能有返回指向列表的指针的全局函数。

如果您需要跟踪更多信息,例如停止触摸的内容,或者在时间步骤之后根据触摸时受影响的事情等做一些事情,则需要更多信息工作,变得更具体。您可能会发现这些教程很有用:

这个使用BeginContact / EndContact更新一个正在触摸的其他东西的列表,并使用它来决定玩家是否可以在任何给定时间跳转: http://www.iforce2d.net/b2dtut/jumpability

这个方法使用类似的方法来查看当前汽车轮胎下的表面类型,以确定表面有多少摩擦力: http://www.iforce2d.net/b2dtut/top-down-car

这个使用PreSolve来决定两个物体(箭头和目标)在撞击时是否应该粘在一起,这取决于撞击的速度。实际的“粘在一起”处理在时间步骤结束后完成: http://www.iforce2d.net/b2dtut/sticky-projectiles

答案 1 :(得分:0)

我认为您只需调用GetContactList,然后使用迭代器处理所有联系人,如果您需要在其他地方执行此操作