现在的位置: 首页 > 综合 > 正文

[cocos2d-x]Box2D 碰撞过滤规则

2013年09月02日 ⁄ 综合 ⁄ 共 5076字 ⁄ 字号 评论关闭

原文链接:http://blog.csdn.net/zhangxaochen/article/details/8071232

首先注意这个函数:

函数实现位于 b2WorldCallbacks.cpp line:24

这是默认的碰撞过滤回调函数。
由函数实现可以看出, 当 filterA.groupIndex == filterB.groupIndex 时, 若二者 groupIndex >0, 两个fixture一定碰撞; 若 groupIndex<0,二者一定不碰撞。

如果两个 fixture 的 groupIndex 不相等, 那么再判断 二者中是否有一方的 maskBits 包含了另一方的 categoryBits, 即代码里的“&运算”不为零——如果是,返回 true; 否则返回 false。

由此可以看出:
1. 默认的碰撞标记优先级为: groupIndex 高于 maskBits+categoryBits
2. (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0 表示A, B 的 maskBits, categoryBits,必须互相包含包含对方, 函数才返回 true。 举例说明: 如果 filterA.categoryBits=1, filterB.categoryBits=2, filterA.maskBits=3, filterB.maskBits=2, 那么虽然
(3&2)!=0, 但是 (2&1)==0, 所以AB不会碰撞。假设这里的A、B分别代表“一种”而不是“一个”fixture的话,那么可以判定 A种种内相互碰撞, B种种内也相互碰撞。

===================================================
那么, 怎么使用自定义 ShouldCollide 函数呢?
简单的演示一下。
1. 自定义 b2ContactFilter 的一个子类:

2. 在你 new b2World(gravity) 的地方,紧接着添加:

这样一来,不管你怎么设定 fixture 的 groupIndex, maskBits, categoryBits 所有的 body 都会碰撞。
【注意】 在 box2d 里面, b2World, b2ContactFilter, b2ContactListener 是少有的几个不被引擎管理, 而需要自己 new 的类, 一定要记得在析构函数中 delete 他们。 如果 自定义的 contactFilter 不是成员变量,可以在析构函数里这么释放:

======================================================
再来看看一个引擎里的例子: TestCpp - Box2DTestBed 里的 CollisionFiltering.h (函数实现都在这个头文件里了)
我们只看文件开始定义的这几个常量:

假设我们没有去覆写 ShouldCollide, 就用的引擎默认的函数。可以看出,smallGroup (对应场景里的小物体 ) 必然碰撞,因为 k_smallGroup = 1 大于 0; k_largeGroup (大物体) 互相一定不碰撞, 因为 -1<0 。

而对于大小物体之间,因为
k_triangleMask = 0xFFFF;
k_boxMask = 0xFFFF ^ k_triangleCategory; // 这样 boxMask 就不“包含” triangleCategory  了
k_circleMask = 0xFFFF;

所以小三角和大方块不碰撞,大三角和小方块也不碰撞, 其他的大物体和小物体都会碰撞

 

原文链接:http://blog.csdn.net/zhangxaochen/article/details/8071232

{{OVER}}

原文链接:http://blog.csdn.net/zhangxaochen/article/details/8071232

首先注意这个函数:

函数实现位于 b2WorldCallbacks.cpp line:24

这是默认的碰撞过滤回调函数。
由函数实现可以看出, 当 filterA.groupIndex == filterB.groupIndex 时, 若二者 groupIndex >0, 两个fixture一定碰撞; 若 groupIndex<0,二者一定不碰撞。

如果两个 fixture 的 groupIndex 不相等, 那么再判断 二者中是否有一方的 maskBits 包含了另一方的 categoryBits, 即代码里的“&运算”不为零——如果是,返回 true; 否则返回 false。

由此可以看出:
1. 默认的碰撞标记优先级为: groupIndex 高于 maskBits+categoryBits
2. (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0 表示A, B 的 maskBits, categoryBits,必须互相包含包含对方, 函数才返回 true。 举例说明: 如果 filterA.categoryBits=1, filterB.categoryBits=2, filterA.maskBits=3, filterB.maskBits=2, 那么虽然
(3&2)!=0, 但是 (2&1)==0, 所以AB不会碰撞。假设这里的A、B分别代表“一种”而不是“一个”fixture的话,那么可以判定 A种种内相互碰撞, B种种内也相互碰撞。

===================================================
那么, 怎么使用自定义 ShouldCollide 函数呢?
简单的演示一下。
1. 自定义 b2ContactFilter 的一个子类:

2. 在你 new b2World(gravity) 的地方,紧接着添加:

这样一来,不管你怎么设定 fixture 的 groupIndex, maskBits, categoryBits 所有的 body 都会碰撞。
【注意】 在 box2d 里面, b2World, b2ContactFilter, b2ContactListener 是少有的几个不被引擎管理, 而需要自己 new 的类, 一定要记得在析构函数中 delete 他们。 如果 自定义的 contactFilter 不是成员变量,可以在析构函数里这么释放:

======================================================
再来看看一个引擎里的例子: TestCpp - Box2DTestBed 里的 CollisionFiltering.h (函数实现都在这个头文件里了)
我们只看文件开始定义的这几个常量:

假设我们没有去覆写 ShouldCollide, 就用的引擎默认的函数。可以看出,smallGroup (对应场景里的小物体 ) 必然碰撞,因为 k_smallGroup = 1 大于 0; k_largeGroup (大物体) 互相一定不碰撞, 因为 -1<0 。

而对于大小物体之间,因为
k_triangleMask = 0xFFFF;
k_boxMask = 0xFFFF ^ k_triangleCategory; // 这样 boxMask 就不“包含” triangleCategory  了
k_circleMask = 0xFFFF;

所以小三角和大方块不碰撞,大三角和小方块也不碰撞, 其他的大物体和小物体都会碰撞

 

原文链接:http://blog.csdn.net/zhangxaochen/article/details/8071232

{{OVER}}

抱歉!评论已关闭.