【问题标题】:Getting the world's contactListener in Box2D在 Box2D 中获取世界的contactListener
【发布时间】:2012-06-02 23:29:06
【问题描述】:

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

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

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

我知道我可以将引用传递给需要它的其他类,但我想知道是否有更好的方法。更具体地说,虽然我找不到执行此操作的方法,但是否有类似的方法:

world->GetContactListener();

在 Box2D 中?

我尝试这样做的原因仅仅是因为我更愿意将一些游戏逻辑(即身体是否能够根据来自接触侦听器的信息进行跳跃)移动到相关类本身,而不是将所有内容都放入主要的游戏类。

谢谢!

【问题讨论】:

  • 接触式监听器的重点是当事情发生时你等待它告诉你,你不要自己去问它。也许你可以让接触监听器调用游戏对象中的一个函数,让他们知道他们触摸了哪些其他对象。
  • @iforce2d 这不一定是真的。只有在为当前步骤计算了模拟之后,您才不能更改您的 box2d 实体状态。并且接触侦听器用于在完成后分析当前的模拟步骤。
  • 什么不正确?我在哪里说过他应该在时间步内改变身体状态?在时间步长期间调用联系侦听器 - 然后您可以分析事物,只要在时间步长之后之前不更改 Box2D 世界中的任何内容。回到最初的问题,联系人监听器只是作为 BeginContact、EndContact、PreSolve 和 PostSolve 四个函数的入口点。通常它没有成员变量,所以没有理由得到它,因为没有什么可以从 得到它。也许我们应该问问乔恩,如果他能找到听众,他会怎么做。
  • @iforce2d 如果您将其添加为答案,我会将其标记为正确

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


【解决方案1】:

联系人监听器只是作为 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!!

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

如果您需要跟踪更多信息,例如哪些东西停止触摸,或者在时间步之后根据触摸时事物的影响程度等做某事,则需要更多时间工作并变得更加具体。您可能会发现这些教程很有用:

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我特别想访问ContactListener 类的成员变量,所以很遗憾这对我没有帮助。
    • 在这种情况下,您可以提供对您的联系人侦听器的访问,将其创建为单例或使其成为某个全局数据类的实例,如果您拥有它,但我真的不认为您应该这样做。
    猜你喜欢
    • 2015-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多