使用filter筛选刚体碰撞

  有时候需要避免刚体间的碰撞,那么可以使用filter。它是框架的一个属性,提供了碰撞筛选功能。用法比较有意思,经过了多次的试错,才找到其规则,因此有必要进行一些总结。

  filter有三个属性,可以从引擎源代码得知:

struct b2Filter
{
    b2Filter()
    {
        categoryBits = 0x0001;
        maskBits = 0xFFFF;
        groupIndex = 0;
    }

    /// The collision category bits. Normally you would just set one bit.
    uint16 categoryBits;

    /// The collision mask bits. This states the categories that this
    /// shape would accept for collision.
    uint16 maskBits;

    /// Collision groups allow a certain group of objects to never collide (negative)
    /// or always collide (positive). Zero means no collision group. Non-zero group
    /// filtering always wins against the mask bits.
    int16 groupIndex;
};

  这三个属性都是uint16类型的,其中categoryBits和maskBits用二进制来表示(用十六进制初始化,但是是二进制用法)。关于每个属性的意义,虽然英文注释已经说明了很多了,但只有经过了实践,方才真正理解。在查阅了BOX2D手册后,得知filter有两种碰撞筛选策略。

1.categoryBits和maskBits组合判断

  categoryBits代表该刚体所属的种族,它的值要设置成2的N次方,这是因为其16位二进制数只能有一位是1,其余都是0。maskBits代表该刚体被允许碰撞的刚体种群(即另一个刚体的categoryBits)。根据这两个属性,引擎给出了一个碰撞筛选规则:

uint16 catA = fixtureA.filter.categoryBits;
uint16 maskA = fixtureA.filter.maskBits;
uint16 catB = fixtureB.filter.categoryBits;
uint16 maskB = fixtureB.filter.maskBits;
if ((catA & maskB) != 0 && (catB & maskA) != 0)
{
 // fixtures can collide
}

  可以看出,两个刚体要相撞,必须是“你情我愿”的,一方不愿意,那么就撞不了了。又从maskBits默认值0xFFFF得知,默认情况下,一个刚体是被允许和任意刚体发生碰撞的,当然这个刚体必须是动态刚体。

  那么,如何设置刚体的maskBits的值使其允许和一个以上的刚体发生碰撞呢?那就是使用按位或操作:|,这样该刚体的maskBits和要碰撞的刚体的categoryBits做&操作后,就都不会为0了,满足了碰撞筛选规则。如下代码所示,cat_b2代表的刚体,被允许和和cat_ground刚体以及cat_b1刚体都发生碰撞:

fixturedef.filter.categoryBits = cat_b2;
fixturedef.filter.maskBits = cat_ground | cat_b1;

2.group分组判断

  这个比较简单,但要使其生效,那么两个刚体的groupIndex属性值必须一致且不为0。接下来再判断其值的正负,正一定相撞,负一定不相撞。且一旦满足了group分组判断策略,categoryBits和maskBits组合判断策略就无效了。也就是说该判断策略的优先级要高。如下代码所示,fixture1和fixture2是一定相撞的(相等、不为0,正),而fixture3和fixture4是一定不相撞的(相等,不为0,负):

fixture1Def.filter.groupIndex = 1;
fixture2Def.filter.groupIndex = 1;
fixture3Def.filter.groupIndex = -1;
fixture4Def.filter.groupIndex = -1;

动态地改变刚体的碰撞规则

  除了通过初始化filter的各种属性来指定碰撞规则,还可以通过b2Fixture::SetFilterData函数随时改变刚体框架的filter,从而根据游戏逻辑需求动态地改变刚体的碰撞规则。

posted @ 2015-04-15 22:53  Demon90s  阅读(838)  评论(0编辑  收藏  举报