您的位置:首页 > 其它

姜老师的豆知识——box2d中DestroyBody时可能遇到的问题

2015-04-12 12:19 197 查看
原文链接

我写了一个简单的测试,先创建了几个形状的“方块”, 各种形状,有圆的,有方的,有不规则的。 有时,我们需要组合一些形状,来组成我们想要的形状, 例如,雷神的锤的形状。这里可以简单的看成是一个 字母 T 的形状,用两个矩形可以组成一个类似锤的形状。当创建了这些形状后,我又创建了“子弹”。用一个圆形来表示子弹。思路是,给子弹一个速度,之后子弹撞击到任意一个形状后,子弹消失。我使用了接口b2ContactListener,通过回调函数virtual void BeginContact(b2Contact* contact);来获取子弹碰撞的信息。

b2Fixture* fixtureA = contact->GetFixtureA();

b2Fixture* fixtureB = contact->GetFixtureB();

b2Body* bodyA = fixtureA->GetBody();

b2Body* bodyB = fixtureB->GetBody();

到了这里,

通过

bodyA->GetUserData();

来获取这两个b2Body代表的是什么类型。

如果是子弹类型,

消除这个子弹。

我直接使用了语句

box2dWorld->DestroyBody(bodyA);

子弹碰撞到其他形状后,没有被消除。

原因是,此时的 box2dWorld 是“上锁的”,不能直接在回调函数中调用DestoryBody方法,

引用一个网上找到的英文解释

If you are trying to do this inside the world's Step() function (eg in a contact listener), it will not work because the world is still processing the bodies.

You will need to make a note of which bodies you want to destroy, and then destroy them after the world's time step has finished.

于是,当检测到了一个子弹是碰撞的,用一个vector来存储b2Body,

在b2World调用函数Step之后, 再来DestoryBody 。

修改后,重新运行,这次子弹被消除了。

不过,之后,我又碰到了一个BUG,在子弹碰撞一个特殊形状的盒子时,有一定的概率会发生中断。

我们再来看一下判断碰撞的代码,

b2Fixture* fixtureA = contact->GetFixtureA();

b2Fixture* fixtureB = contact->GetFixtureB();

b2Body* bodyA = fixtureA->GetBody();

b2Body* bodyB = fixtureB->GetBody();

我们通过一个 b2Fixture来获取一个b2Body,

如果一个物体像是锤子那样,有两个 b2Fixture, 而子弹又正好同时击中了这两个部分,

那么就有可能会将一个b2Body 消除两次。

于是,加了一个判断,如果vector里已经有这个b2Body,那么,就不再添加这个b2Body.

问题解决了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: