您的位置:首页 > 其它

(转载)Box2D v2.3.0 用户手册中文版(第1章)-导言

2018-03-18 00:15 483 查看

Chapter 1 导言

1.1 关于

Box2D 是一个用于游戏的 2D 刚体仿真库。程序员可以在他们的游戏里使用它,它可以使物体的运动更加真实,并让游戏世界看起来更具交互性。从游戏引擎的视角来看,物理引擎就是一个程序性动画 (proceduralanimation)的系统。

(译注: 做动画常有两种方法, 一种是预先准备好动画所需的数据,比如图片,再一帧一帧地播放。另一种是以一定方法,动态计算出动画所需的数据,根据数据再进行绘图。

从这种角度看,预先准备的,可称为数据性动画,动态计算的可称为程序性动画。

这个区别,就类似以前我们做历史题和数学题,做历史题,记忆很重要,也就是答案需要预先准备好的。做数学题,方法就很重要,答案是需要用方法推导出来的。

Box2D就是用物理学的方法,推导出那游戏世界物体的位置,角度等数据。而Box2D也仅仅推导出数据,至于得到数据之后怎么处理就是程序员自己的事情了。)

Box2D 是用可移植的 C++ 写成的。引擎中大部分类型的定义都有 b2 前缀,希望这能有效的消除它和你的游戏引擎之间的名字冲突。

1.2 先决条件

在此,我假定你已经熟悉了基本的物理学概念,例如质量、力、扭矩和冲量。如果没有,请先查询一下Google搜索和维基百科。

Box2D是游戏开发者大会(Game Developer Conference,GDC)的物理学教程的一部分。你可以从box2d.org的下载页面获得这些教程。

因为 Box2D 是用 C++ 写成的,所以你应该具备 C++ 程序设计的经验。Box2D 不应该成为你的第一个 C++ 程序项目。你应该已经能熟练地编译,链接和调试了。

注意

Box2D 不应该成为你的第一个 C++ 程序项目。你应该已经能熟练地编译,链接和调试了。网络上有很多关于C++的资料。

1.3 关于手册

这个手册包含了主要的Box2D的API,但并不是每一个都包含了 。你可以通过阅读Box2D自带的testbed程序的代码来学习更多的东西。而且Box2D代码的注释已经按照Doxygen格式编写,可以很容易的创建超链接形式的API文档。

这个手册只在新版本发布的时候更新。因此相比版本库中的代码版本,它可能已经过时了。

1.4 反馈和报告BUG

如果你有关于Box2D的问题或者反馈意见,请在论坛留言。这也是社区讨论的好地方。

Box2D使用 Google code project来跟踪问题。这是个很好的方式,它可以确保你的问题不会淹没在论坛之中。

请在这里列出BUG和功能需求: http://code.google.com/p/box2d/

如果你能提供更有效的细节的话,就能确保你的问题得到解决。一个用于复现问题的testbed用例是很有意义的。你可以在随后章节读到和testbed相关的内容。

1.5 核心概念

Box2D 中有一些基本的概念和对象,这里我们先做一个简要的定义,在随后的章节里会有更详细的描述。

形状(shape)

形状是一个2D的几何对象。例如圆或多边形。

刚体(rigid body)

一块十分坚硬的物质,它上面的任何两点之间的距离都是完全不变的。它们就像钻石那样坚硬。在后面的讨论中,我们用物体(body)来指代刚体。

夹具(fixture)

夹具将形状绑定到物体上,并添加密度(density)、摩擦(friction)和恢复(restitution)等材料特性。夹具还将形状放入碰撞系统(碰撞检测(Broad Phase))中,以使之能与其他形状相碰撞。

(译注: 一个物体和另一物体碰撞, 碰撞后速度和碰撞前速度的比值会保持不变,这比值就叫恢复系数。)

(译注: Broad Phase是碰撞检测的一个子阶段, 将空间分割, 每个空间对应一个子树, 物体就放到树中, 不同子树内的物体不可能相交不用去计算, 在同一个子树由对应的算法再计算出接触点等信息。因为这是远距碰撞检测,就叫Broad Phase, 接下来还有Narrow Phase。)

约束(constraint)

约束(constraint)就是消除物体自由度的物理连接。一个2D物体有3个自由度(两个平移坐标和一个旋转坐标)。如果我们把一个物体钉在墙上(像摆锤那样),那我们就把它约束到了墙上。这样,此物体就只能绕着这个钉子旋转,因此这个约束消除了它 2 个自由度。

接触约束(contact constraint)

一种防止刚体穿透,并模拟摩擦和恢复的特殊约束。你不必创建接触约束,它们会自动被 Box2D 创建。

关节(joint)

它是一种用于把两个或更多的物体固定到一起的约束。Box2D 支持若干种关节类型: 旋转、棱柱、距离等等。有些关节拥有限制(limits)和马达(motors)。

关节限制(joint limit)

关节限制限定了关节的运动范围。例如,人类的胳膊肘只能做某一范围角度的运动。

关节马达(joint motor)

关节马达能依照关节的自由度来驱动所连接的物体。例如,你可以使用马达来驱动胳膊肘的旋转。

世界(world)

物理世界就是相互作用的物体,夹具和约束的集合。Box2D 支持创建多个世界,但这通常是不必要或不推荐的。

求解器(solver)

物理世界使用求解器来推算时间,求解接触和关节约束。Box2D的求解器是一种高性能的迭代求解器,它会顺序执行N次,这里的N是约束的个数。

(译注: 即算法的复杂度为O(N)。)

连续碰撞(continuous collision)

求解器使用时域上的离散时间步来推算物体状态。如果没有特殊处理的话,这会导致隧穿效应。

(译注: 假设我们采用1s的固定时间间隔来推算一个物理系统的运动。那么如果这个系统中有两个物体在某一秒的0.5s的时刻,发生碰撞的话。死板的采用固定时间间隔计算的方法,就会导致物体实际上越过了碰撞点的现象发生,这就是隧穿效应。解决的办法显然是要估算出碰撞发生的时刻,并做相应的处理,这也是下一段提到的TOI的含义。)



Box2D拥有特殊的算法来处理隧穿效应。首先,碰撞算法能够在两个物体的运动过程中进行插值运算,以找到首次碰撞时间 (the first time of impact,TOI)。接着,一个分步求解器将物体移动到它们的TOI时刻,并对碰撞求解。

1.6 模块

Box2D由三个模块组成: 通用模块(Common),碰撞模块(Collision) 和力学模块(Dynamics). 通用模块包含了内存分配、数学和配置的代码。碰撞模块定义形状、碰撞检测和碰撞的函数或队列。最终力学模块提供对世界、物体、夹具和关节的模拟。



1.7 单位

Box2D使用浮点数,所以必须使用公差来保证它正常工作。这些公差已经被调谐得适合米-千克-秒(MKS)单位制。尤其是,Box2D已被调谐得能良好地处理0.1到10米之间的移动物体。这意味着从罐头盒到公共汽车大小的对象都能良好地工作。静态的物体就算大到50米都没有问题。

作为一个2D物理引擎,使用像素作为单位是很诱人的。但很不幸,那将导致不良的模拟,也可能会造成古怪的行为。一个200像素长的物体在Box2D看来就有45层建筑那么大。

注意

Box2D 已被调谐至 MKS 单位。移动物体的尺寸应该保持在大约 0.1 到 10 米之间。当你渲染场景和角色时, 可能要用到一些比例缩放系统。Box2D自带的testbed例子,使用了OpenGL的视口变换。不要使用像素!!!

最好把Box2D中的物体看作是被贴上了你的艺术创作品的移动广告板。这个广告板在一个以米为单位的系统里运动,但你可以利用简单的比例因子把它转换为像素坐标。之后就可以使用这些像素坐标去确定你的精灵(sprites)的位置,等等。你也可以将它的坐标轴翻转过来。

(译注: 坐标轴翻转的含义是比例因子可以为负数。)

Box2D里的角使用弧度制。物体的旋转角度以弧度方式存储,并可以无限增大。如角度变得太大,可考虑将角度进行规范化。(使用b2Body::SetAngle)

注意

Box2D使用弧度,而不是度。

1.8 工厂和定义

快速内存管理在 Box2D API 的设计中担当了一个中心角色。所以当你创建一个 b2Body 或一个 b2Joint时,你需要调用 b2World 的工厂函数(factory functions)。你不应以别的方式为这些类型分配内存。

这些是创建函数:

b2Body* b2World::CreateBody(const b2BodyDef* def)
b2Joint* b2World::CreateJoint(const b2JointDef* def)


这些是对应的销毁函数:

void b2World::DestroyBody(b2Body* body)
void b2World::DestroyJoint(b2Joint* joint)


当你创建物体或关节时,需要提供定义(definition)。这些定义包含了创建物体或关节时所需的所有信息。使用这样的方法,我们能够预防构造错误,保持较少的函数参数数量,提供有意义的默认值,并减少访问子(accessor)的个数。

因为fixture必须有父body,所以要使用b2Body的工厂方法来创建并销毁它们。

b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def)
void b2Body::DestroyFixture(b2Fixture* fixture)


也有个简便的方法直接用形状和密度来创建fixture。

b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float32 density)


工厂并不保留定义的引用,因此你可以在栈上创建定义,并在临时资源中保存它们。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: