Box2D v2.3.0 用户指南(第七章)

103 篇文章 0 订阅
53 篇文章 0 订阅



第七章装置(fixture)

7.1简介

回想一下,我们曾经说过形状并不知道它依附于的物体的存在,它们能够在物理模拟中独立使用。因此Box2D提供了b2Fixture类来讲形状附加到物体上。一个物体可以没有装置,也可以由多个装置,一个有一个以上装置的物体通常称为一个组合体(compoundbody)。

装置有以下组成元素:

·一个单独的形状

·broad-phase代理(可以有多个)

·密度(density),摩擦力(friction)和弹力(restitution

·碰撞过滤标记(collision filtering flags

·指回父物体的指针

·用户数据(user data

·传感器标记(sensor flag

 

7.2创建装置

要创建一个装置,首先需要初始化一个装置定义(fixturedefinition),然后将装置定义作为参数传给父物体的方法:

b2FxitureDeffixtureDef;

fixtureDef.shape= &myShape;

fixtureDef.density= 1.0f;

b2Fixture*myFixture = myBody->CreateFixture(&fixtureDef);

这段代码创建好一个装置,并且将这个装置附加到物体上。你不需要去保存这个装置的指针,因为当父物体被析构的时候,这个附加到物体上的装置也会被自动析构。你可以创建多个装置附加到物体上。

你可能需要析构一个物体上的装置,以此来模拟一个可分裂的对象,否则的话,你不需要去管它们,让物体的析构函数来替你处理掉附加的装置就可以了。

myBody->DestoryFixture(myFixture);

 

密度

装置的密度是用来计算父物体的质量的,密度可以是0甚至是负数,你应该为所有的装置使用相似的密度,这样做可以提高堆叠的稳定性。

当你设置密度时,物体的质量并不会随之发生改变,你必须要手动调用ResetMassData方法来重新计算物体的质量。

fixture->SetDensity(5.0f);

body->ResetMassData();

 

摩擦力

摩擦力用来让物体更真实的沿着其他对象滑动,Box2D支持静摩擦力(staticfriction)和动摩擦力(dynamicfriction),但是二者使用同一个属性值进行设置。摩擦力在Box2D中能够被精确模拟,摩擦力的大小等于接触面的压力(normalforce)乘以摩擦系数,这种称为Coulombfriction(库伦摩擦)。摩擦系数通常在0到1之间,但是任何非负数都是有效的。当摩擦系数为0时,物体表面没有摩擦力,当摩擦系数为1时,物体表面会具有很大的摩擦力。在计算两个形状之间的摩擦力时,Box2D会结合两个形状的父装置的摩擦系数,通过计算他们的几何平均值得出:

float32friction;

friction= sqrtf(fixtureA->friction * fixtureB->friction);

因此当其中一个装置具有大小为0的摩擦系数时,整个接触面上就不会有摩擦力存在(摩擦力为0)。

你可以重写b2Contact::SetFriction方法来使用不同的计算方程,这通常实在b2ContactListener的回调函数中完成的。

 

弹性

物体的弹性用来使物体在接触后反弹。弹性系数通常在0到1之间。我们考虑下面的情形:将一个小球坠落在一张桌子上,当弹性系数为0时,小球完全不会弹起(直接就砸到桌子上不动了),这种情况称为(完全)非弹性碰撞;当弹性系数为1时,小球会以完全相同的速度向上弹起(这意味着小球会达到坠落的初始高度,没有能量损失),这称为完全弹性碰撞。两个物体间的弹性系数通过下面的方程来计算:

float32restitution;

restitution= b2Max(fixtureA->restitution, fixtureB->restitution);

弹性系数通过这样的方式来计算,这样你就可以有一个非常有弹力的小球,而不需要有一个非常有弹力的地面了。(注:因为是取二者的较大值,所以小球具有弹力就可以解决问题了)

你可以重写b2Contact::SetRestitution方法来使用不同的计算方程,这通常实在b2ContactListener的回调函数中完成的。

当一个形状执行多次碰撞时,弹性会被近似的模拟,这是由于Box2D使用迭代解析器的缘故。当碰撞的入射速度非常小的时候,Box2D会使用(完全)非弹性碰撞进行模拟,这是为了防止抖动。入射速度的阈值请参考定义在b2Settings.h文件中的b2_velocityThreshold常量。

 

过滤(filtering)

碰撞过滤允许你避免装置间的碰撞。例如:假设你有一个骑自行车的角色,你希望自行车和地形发生碰撞,角色也和地形发生碰撞,但是你不希望你的角色和自行车发生碰撞(因为显然他们彼此重叠),这时你就需要设置过滤标记。Box2D中通过分类(category)和组(group)来支持这种碰撞过滤。

Box2D支持16种碰撞分类,对于每一个装置,你都可以指定它属于某一个碰撞分类,同时你可以指定那些碰撞分类可以与当前装置发生碰撞。举例来说,在一个多人游戏中,你可以指定所有的玩家彼此之间不发生碰撞,所有的怪兽彼此间不发生碰撞,但是玩家和怪兽之间可以发生碰撞。通过指定蒙版标记(masking bits),例如:

playerFixtureDef.filter.categoryBits= 0x0002;

monsterFixtureDef.filter.categoryBits= 0x0004;

playerFixtureDef.filter.maskBits= 0x0004;

monsterFixtureDef.filter.maskBits= 0x0002;

下面是当碰撞能够发生时的判断条件:

uint16catA = fixtureA.filter.categoryBits;

uint16maskA = fixtureA.filter.maskBits;

uint16catB = fixtureB.filter.categoryBits;

uint16maskB = fixtureB.filter.maskBits;

if((catA & maskB) != 0 && (catB & maskA) != 0)

{

// fixtures can collide

}

碰撞组(collisiongroup)允许你指定一个整数的组索引值,你可以设置具有相同组索引值的装置发生碰撞(正索引),也可以设置所有具有相同组索引值的装置不会彼此碰撞(负索引),组索引值通常用于以某种方式相关联的物体之间,比如自行车的部件。在下面的例子中,fixture1和fixture2会发生碰撞,fixture3和fixture4不发生碰撞:

fixture1Def.filter.groupIndex= 2;

fixture2Def.filter.groupIndex= 2;

fixture3Def.filter.groupIndex= -8;

fixture4Def.filter.groupIndex= -8;

具有不同组索引值的装置在发生接触的时候,通过categoryBits和maskBits来判断是否发生碰撞,也就是说,组索引值相比于蒙版标记具有更高的优先级(higherprecedence)。

注意,除了上述过滤规则,Box2D中还有下面的过滤规则:

·静态物体(static)上的装置只能和动态物体发生碰撞

·运动物体(kinematic)上的装置只能和动态物体发生碰撞

·同一个物体上的装置之间不会发生碰撞

·你可以选择“启用/禁用“关节绑定的物体上面的装置的碰撞

有时候你需要为已经创建出来的装置指定碰撞过滤条件,你可以通过调用b2Fixture::GetFilterData和b2Fixture::SetFilterData方法来获取(get)和设置(set)装置的b2Filter结构。需要注意的一点是,修改过滤条件不会在当前时间间隔(timestep)生效,下一个时间间隔才会起作用(参考世界类)。

 

7.3传感器(sensor

有时候游戏逻辑需要知道两个装置重叠在了一起,尽管此时没有发生任何碰撞,这可以通过传感器来实现。传感器是一种能够察觉到碰撞的装置,但是传感器不会响应这个碰撞。

你可以将任何一个装置标记为传感器,传感器可以使静态的(static),运动的(kinematic),或者动态的(dynamic),我们知道一个物体上可以附加多个装置,所以在物体上传感器和真正的装置(非传感器)可以混合存在。此外,当接触的两个物体之中至少有一个动态物体时,传感器才会感知到物体彼此接触,所以传感器无法够捕获这几种物体之间的接触:运动物体-运动物体,运动物体-静态物体,静态物体-静态物体。

传感器不会生成接触点,有两种方法可以得到传感器的状态:

1.   b2Contact::IsTouching

2.   b2ContactListener::BeginContactand EndContact


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值