转自:Complex_ok
第06章 夹具(Fixtures)
回想一下,形状并不知道物体的存在,可以独立使用。因此Box2D需要提供b2Fixture类,用于将形状附加到物体上。 fixture具有下列属性:
• 关联的形状
• 密度(density),摩擦(friction),恢复(restitution)
• 碰撞筛选标记(collision filtering flags)
• 指向父物体的指针
• 用户数据
• 传感器标记(sensor flag)
这些都会在接下来的小节中描述。
要创建fixture,先要创始化一个fixture定义,并将定义传到父物体中。
b2FixtureDef fixtureDef;
fixtureDef.shape = &myShape;
fixtureDef.density = 1.0f;
b2Fixture* myFixture = myBody->CreateFixture(&fixtureDef);
这会创建fixture,并将它附加到物体之上。你不需要保存fixture的指针,因为当它的父物体摧毁时,fixture也会自动被摧毁。 你可以在单个物体上创建多个fixture。.
你也可以摧毁父物体上的fixture,来模拟一个可分裂开的物体。你也可以不理会fixture,让物体的释放函数来摧毁附加其上的fixture。
myBody->DestroyFixture(myFixture);
密度(Density)
fixture的密度用来计算父物体的质量属性。密度值可以为零或者是整数。你所有的fixture都应该使用相似的密度,这样做可以改善物体的稳定性。
当你添加一个fixture时,物体的质量会自动调整。
摩擦(Friction)
摩擦可以使对象逼真地沿其它对象滑动。Box2D支持静摩擦和动摩擦,两者都使用相同的参数。摩擦在Box2D中会被精确地模拟,摩擦力的强度与正交力(称之为库仑摩擦)成正比。摩擦参数经常会设置在0到1之间, 也能够是其它的非负数,0意味着没有摩擦, 1会产生强摩擦。当计算两个形状之间的摩擦时,Box2D必须联合两个形状的摩擦参数。这是通过以下公式完成的:
float32 friction;
friction = sqrtf(shape1->friction* shape2->friction);
所以当其中一个fixture的摩擦参数为0时,接触的摩擦就为0。
恢复(Restitution)
恢复可以使对象弹起。恢复的值通常设置在0到1之间。想象一个小球掉落到桌子上,值为0表示着小球不会弹起, 这称为非弹性碰撞。值为1表示小球的速度跟原来一样,只是方向相反, 这称为完全弹性碰撞。恢复是通过下面的公式合成的:
float32 restitution;
restitution = b2Max(shape1->restitution,shape2->restitution);
ixture会携带碰撞筛选信息,让你防止某些游戏对象相互碰撞。
当一个形状多次碰撞时,恢复会被近似地模拟。Box2D使用了迭代求解器,当冲撞速度很小时,Box2D也会使用非弹性碰撞,这是为了防止抖动。
筛选(Filtering)
碰撞筛选是一个防止某些形状发生碰撞的系统。比如,你创造了一个骑自行车的角色。你希望自行车与地形之间有碰撞,角色与地形有碰撞,但你不希望角色和自行车之间发生碰撞 (因为它们必须重叠)。Box2D通过种群和分组支持了这样的碰撞筛选。
Box2D支持16个种群。任意fixture你都可以指定它属于哪个种群。你还可以指定这个fixture可以和其它哪些种群发生碰撞。例如,你可以在一个多人游戏中指定玩家之间不会碰撞,怪物之间也不会碰撞,但是玩家和怪物会发生碰撞。这是通过掩码来完成的,例如:
playerFixtureDef.filter.categoryBits= 0x0002;
monsterFixtureDef.filter.categoryBits= 0x0004;
playerFixtureDef.filter.maskBits =0x0004;
monsterFixtureDef.filter.maskBits =0x0002;
碰撞分组让你指定一个整数的组索引。你可以让同一个组的所有fixture总是相互碰撞(正索引)或永远不碰撞(负索引)。组索引通常用于一些以某种方式关联的事物,就像自行车的那些部件。在下面的例子中,fixture1 和 fixture2 总是碰撞,而 fixture3 和 fixture4 永远不会碰撞。
fixture1Def.filter.groupIndex = 2;
fixture2Def.filter.groupIndex = 2;
fixture3Def.filter.groupIndex = -8;
fixture4Def.filter.groupIndex = -8;
如果组索引不同,碰撞筛选就会按照种群和掩码来进行。换句话说, 分组筛选与种群筛选相比,具有更高的优选级。
注意在 Box2D 中还有其它的碰撞筛选,这里是一个列表:
• static物体上的fixture永远不会与另一个static体上的fixture发生碰撞
• 同一个物体上的fixture永远不会相互碰撞
• 如果两个物体用关节连接起来,物体上面的fixture可以选择启用或禁止它们之间相互碰撞
有时你可能希望在形状创建之后去改变其碰撞筛选。 你可以使用b2Shape::GetFilterData 以及 b2Shape::SetFilterData来访问及设置已存在fixture的b2FilterData结构。注意就算修改了筛选数据,下一个时间步为止,现在的接触并不会增加或删除(见world类)。
有时候游戏逻辑需要判断两个fixture是否相交,但却不应该有碰撞反应。这可以通过传感器(sensor)来完成。传感器也是个fixture,但只会侦测碰撞而不产生其它反应。
你可以将任一fixture标记为传感器。传感器可以是static或dynamic的。记住,每个物体上可以有多个fixture, 传感器和实体fixture是可以混合存在的。
传感器不会生成接触点。这里有两种方法得到传感器的状态:
1. b2Contact::IsTouching
2. b2ContactListener::BeginContact 和 EndContact