Box2D 碰撞组

12

有没有人知道当 (body1.categoryBits & body2.maskBits) && (body1.maskBits & body2.categoryBits) 时,物体是否只会相撞? 或者当 (body1.categoryBits & body2.maskBits) || (body1.maskBits & body2.categoryBits) 时,它们已经发生了碰撞?

5个回答

31

15

来自Box2D 手册的内容:

6.2.3. 筛选

碰撞筛选是一个防止形状发生碰撞的系统。 例如,假设你制作了一个骑自行车的角色。 你希望自行车与地形碰撞,并且角色与地形碰撞, 但不希望角色与自行车发生碰撞(因为它们必须重叠)。 Box2D 使用类别和组支持这样的碰撞筛选。

Box2D 支持 16 种碰撞类别。 对于每个形状,您可以指定它属于哪个类别。 您还可以指定此形状可以与哪些其他类别发生碰撞。 例如,在多人游戏中,您可以指定所有玩家彼此不发生碰撞, 怪物之间也不会相互碰撞,但玩家和怪物应该发生碰撞。 这是使用掩码位完成的。例如:

playerShapeDef.filter.categoryBits = 0x0002;
monsterShapeDef.filter.categoryBits = 0x0004;
playerShape.filter.maskBits = 0x0004;
monsterShapeDef.filter.maskBits = 0x0002;

碰撞组允许您指定一个整数组索引。您可以使所有具有相同组索引的形状始终发生碰撞(正索引),或永远不会发生碰撞(负索引)。组索引通常用于某些相关的事物,例如自行车的各个部分。在下面的示例中,shape1和shape2始终发生碰撞,但shape3和shape4永远不会碰撞。

shape1Def.filter.groupIndex = 2;
shape2Def.filter.groupIndex = 2;
shape3Def.filter.groupIndex = -8;
shape4Def.filter.groupIndex = -8;

不同分组索引的形状之间的碰撞会根据类别和掩码位进行过滤。换句话说,分组过滤具有高于类别过滤的优先级。


12
这是我理解maskBits和categoryBits的方式。假设你有三个物体:objectA,objectB和objectC。
为每个对象定义一个类别:
objectA.categoryBits = 0x0002; objectB.categoryBits = 0x0004; objectC.categoryBits = 0x0008;
然后,设置maskBits,为每个categoryBits定义碰撞规则:
-> objectA与所有物体(0xFFFF)相碰撞,但不与objectB(0x0004)相碰撞。 objectA.maskBits = 0xFFFF & ~0x0004;
-> objectB与objectA(0x0002)或objectC(0x0008)相碰撞,但不与其他任何物体相碰撞。 objectB.maskBits = 0x0002 | 0x0008;
-> objectC与objectA(0x0002)相碰撞,但不与其他任何物体相碰撞。 objectC.maskBits = 0x0002;
我不知道这是否正确,但对我而言有效。
希望对您有所帮助。

3

查看Box2d源码,发现如果夹具属于不同的组(或组为0),则进行以下类别和掩码比较:

    bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && 
                   (filterA.categoryBits & filterB.maskBits) != 0;

看起来只有在两个fixture的掩码都允许碰撞时,fixture才会发生碰撞。(即:AND逻辑)

0

我使用了墙和许多玩家(我们的玩家和敌人)。我的玩家和敌人与墙碰撞,但彼此之间不会碰撞。我已经这样做了,它起作用了。您必须将groupIndex设置为负值,以使对象彼此不发生碰撞。像这样定义夹具。

    /* The categories. */
public static final short CATEGORYBIT_WALL = 1;
public static final short CATEGORYBIT_PLAYERS = 2;

/* And what should collide with what. */
public static final short MASKBITS_WALL = CATEGORYBIT_WALL + CATEGORYBIT_PLAYERS;

public static final FixtureDef WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f, false, CATEGORYBIT_WALL, MASKBITS_WALL, (short)0);
public static final FixtureDef PLAYERS_FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f, false, CATEGORYBIT_PLAYERS, MASKBITS_WALL, (short)-1);

并应用于您的身体。

AnimatedSprite player, enemy;
Body playerBody, enemyBody;

player= new AnimatedSprite(CAMERA_WIDTH/2, CAMERA_HEIGHT/2,     this.playerRegion, this.getVertexBufferObjectManager());
playerBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld, player,     BodyType.DynamicBody, PLAYERS_FIXTURE_DEF);   
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(player, playerBody, true, false));

enemy= new AnimatedSprite(CAMERA_WIDTH/4, CAMERA_HEIGHT/2, this.enemyRegion, this.getVertexBufferObjectManager());

enemyBody= PhysicsFactory.createCircleBody(this.mPhysicsWorld, enemy, BodyType.DynamicBody, PLAYERS_FIXTURE_DEF);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(enemy, enemyBody, true, false));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接