当你用到box2d后,box2d的碰撞监听检测 是最常用的内容之一。
在这里简要说明一下,为后面的内容做点铺垫。呵呵
1.通过继承并实现b2ContactListener这个类,
class MyContactListener : public b2ContactListener { …… }
2.进源代码你可以看到这个类中有 4个回调函数,
class MyContactListener : public b2ContactListener {
//碰撞开始 即发现物体间重叠点时通知 virtual void BeginContact(b2Contact* contact); /// 碰撞结束 结束重叠后通知 virtual void EndContact(b2Contact* contact) ; //碰撞处理前 即根据物理定律处理刚体前 virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold); //碰撞处理后
virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
}
重写这4个函数。在相关的函数中加入你想要碰撞处理的内容。 即可
3.把你这个监听类加入到世界中
world->SetContactListener(mContactListener);
你就可以监听碰撞事件了。
这里有几个注意的地方:
1。我们不能在上面这几个回调函数中删除摧毁刚体。因为上面调用都是在box2d的b2World::Step方法中,此时正在进行遍历物理世界的world->GetBodyList()
对物理时间世界进行演算。
官方说明:“你可能会以碰撞来施加伤害,并试图摧毁关联的角色和它的刚体。然而,Box2D 并不允许你在回调中改变物理世界,因 为你可能会摧毁 Box2D 正在运算的对象,造成野指针。”
如果强在里面加摧毁物体函数,你可能会发现world是被锁定的。如需要摧毁,只能用一个容器把需要的处理事件保存起来,带step方法执行完毕后再处理这些容器;具体的摧毁动态刚体的方法在下下章写。。。
2。如果你在PreSolve()里改变了物体的位置,比如使他们后退一点,他们互不碰撞,那么他们不会调用EndContact();
3。你有时候很希望他们可以选择碰撞的方向:比如 天上一堵墙 从下面可以穿过不会碰撞,上面接触会碰撞 不能穿过。这属于box2d中OneSidedPlatform的内容。具体的我会在下一章写。
但要注意 如果你想碰撞后修改成穿过的状态 应该用 contact->SetEnabled(false); 而不是 myShapeDef.isSensor = true; 你在代码里可以尝试下两个的区别。还是有点小明显。虽然isSensor 是让
传感器会侦测碰撞而不产生碰撞反应。
box2d单纯的碰撞检测还是比较好看明白。还是附个小例子吧~
下载例子dome :附件