box2d物理引擎自学笔记整理1
由于之前查资料时没有留意box2d中文教程中物理引擎使用的版本号,后来写代码发现,很多地方有差别,回头上官下了文档后,发现,最新版本已经更新到
2.2.1,而之前的上网找到的box2d中文教程是2.0。很抱歉没有留意到版本信息,现在我参考的资料是官方最新的文档内容。
想要了解更详细内容,读者可以到网上查阅。这里给出一个下载地址:http://box2d.org/
同时,我这里给出一个中文版的翻译,大家可以参考中文版来阅读英文版文档,http://blog.csdn.net/complex_ok/article/category/871440;
一、重要概念
(1)形状(shape)
一个2D的几何物体,例如像圆或者多边形。
(2)刚体(rigid body)
就是一块十分坚硬的物质,它上面的任何两点之间的距离是完全不变。通常用物体(body)来代替刚体。
(3)夹具(fixture)
夹具是将形状捆绑到物体上,同时增加一些物理属性,如密度、摩擦和恢复。
(4)约束(constraint)
一个约束就是消除物体自由度的物理连接。自由度在物理上的定义是:完全确定一个物体在空间位置所需要的独立坐标数目。
在2D世界中,一个物体的自由度就是3,而不是2。要注意的是物体不是我们在数学中的一个点的坐标(x, y),如果是一个点(没有体积、大小)
,那它的自由如当然是2,但这里的物体是有体积、大小的。举例来说,想要确定一把尺子在2D世界中的位置,如果只知道吃上某一点的坐标(x,y),
那还不足以确定尺子的确切位置,因为尺子还可以绕着这个点旋转。故要确定尺子的位置,还需要一个自由度-----rotation(角度),就是说2D世界中,
三个自由度分别是x、y和rotation;
(5)接触约束(contact constraint)
一个防止刚体穿透,以及用于模拟摩擦和恢复的特殊约束。通俗地将就是物体间的摩擦和物体收到挤压后可以恢复原状。
(6)关节(joint)
将多个物体固定到一起的约束。就像人的胳膊。
(7)关节限制(joint limit)
一个关节限制限定了一个关节的运动范围。例如人的胳膊只能做一定角度的旋转。
(8)关节马达(joint motor)
一个关节马达能依照关节的自由度来驱动所连接的物体。例如人可以通过肌肉来趋势胳膊转动。
(9)世界(world)
一个物理世界就是物体,形状和约束相互作用的集合。
(10)解决者(solver)
物理世界的解决者是用来提前时间还有恢复接触和关节约束。
(11)连续的碰撞(continual collision)
解决者通过使用离散的时间点来检测物体。
二、Hello box2d
step1:创建一个世界
box2d程序都是从世界对象的创建开始的。每个物理世界都管理着内存、物体和模拟。
首先是定义重力矢量:
b2Vec2 gravity(0.0f, -10.0f); bool doSleep = true;
这里的gravity包括了大小和方向,方向是沿y轴负方向,大小事该矢量的绝对值即sqrt(0.0的平方 + -10.0绝对值的平方);
接着就是创建世界对象:
b2World world(gravity,doSleep);
step2:创建一个地表
1. 用位置(position), 阻尼(damping)等来定义body
2. 通过world对象来创建body
3. 用形状(shape), 摩擦(friction), 密度(density)等来定义fixture
4. 在body上来创建fixture
既然创建了一个物理世界,这个世界当然就得有个平台来支撑其他物体,就像地球有陆地来支撑森林、建筑等等物体。在box2d中就叫
作地面体,地面体是静态物体,默认的质量为0,它是固定不动的。
(1)创建ground body。
我们需要一个body定义。在定义中,我们指定ground body的初始位置。
b2BodyDef groundBodyDef; groundBodyDef.position.Set(0.0f, -10.0f);
(2)将body定义传給world对象, 创建ground body。
world对象并不保留body定义的引用。ground body是作为静态物体(static body)创建的。静态物体和其它静态物体之间并没有碰撞, 它们是固定的。当body的质量为零时, Box2D就认为它是静态的。物体质量的默认值就为零, 所以它们默认就是静态的。
b2Body* ground = world.CreateBody(&groundBodyDef);
(3)创建地面多边形。
我们用简便函数SetAsBox使得地面多边形构成一个盒子形状,盒子的中心点就是父body的原点。
b2PolygonDef groundBox; groundBox.SetAsBox(50.0f, 10.0f);
SetAsBox函数接收半个宽度和半个高度作为参数。因此在这种情况下,地面盒就是100个单位宽(x轴),20个单位高(y轴)。Box2D已被调谐到使用米,千克和秒做单位。你可以认为长度单位就是米。当物体的大小跟真实世界一样时,Box2D通常工作良好。例如,一个桶约1米高。由于浮点算法的局限性,使用Box2D模拟冰川或沙尘的运动并不是一个好主意。
(4)我们创建shape fixture, 以完成ground body。
我们创建shape fixture, 以完成ground body。这步中,我们有个简便方法。我们并不需要修改fixture默认的材质属性, 可以直接将形状传给body而不需要创建fixture的定义。随后的教程中, 我们将会看到如何使用fixture定义来定制材质属性。
groundBody->CreateFixture(&groundBox, 0.0f);
step3:创建一个动态物体
现在我们已经有了一个地面body,我们可以使用同样的方法来创建一个动态body。除尺寸之外的主要区别是, 我们必须为动态body设置质量属性。
首先我们用CreateBody创建body。默认情况下,body是静态的, 所以在构造时候应该设置b2BodyType使得body成为动态
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.postion.Set(0.0f, 4.0f); b2Body* body = world.CreateBody(&bodyDef);
注意:如果你想body受力的影响而运动, 你必须将body的类型设为b2_dynamicBody。
然后,我们创建一个多边形shapde, 并将它附加到fixture定义上。我们先创建一个box shape:
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(1.0f, 1.0f);
接下来我们使用box创建一个fixture定义。注意, 我们把密度值设置为1,而密度值默认是0。并且,fixture的摩擦系数设置为0.3。
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;//设置密度 shapeDef.friction = 0.3f//设置摩擦系数
使用fixture定义, 我们现在就可以创建fixture。这会自动更新body的质量。要是你喜欢, 你可以为body添加许多不同的fixture。每个fixture都会增加物体的总质量。
body->CreateFixture(&fixtureDef);