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

来源:互联网 发布:淘宝拍立淘不能用了 编辑:程序博客网 时间:2024/05/22 08:26


原著:2007-2013 Erin Catto

翻译:远行的风

关注我的博客:http://blog.csdn.net/qwertyupoiuytr

网上已经有很多版本的Box2D用户手册了,这里我们翻译的是最新的2.3.0这个版本的手册,也是为了更好地学习和理解Box2D这个物理引擎,大部分为个人翻译的,有些地方加入了自己的整理和理解,如果有不恰当的地方,欢迎大家留言批评指正。

1.1简介

Box2D是一款用于游戏的2D刚体仿真引擎。开发者可以在开发游戏时借助这款引擎来让游戏中的物体具有真实地物理效果,例如移动,碰撞等等。从游戏引擎的角度来说,一款物理引擎只是一个动画计算系统而已。

Box2D由可移植的C++语言开发而成,其中大多数类型名称都冠以“b2”这个前缀,以防止这些类型与你的或者其他游戏引擎中的类型名产生冲突。

1.2预备知识

我们假定你已经书记了基本的物理概念,例如质量,力,扭矩和冲量等等。如果你还对其中的概念不熟悉,请先使用GoogleWikipedia查询和学习相关的知识。

Box2D的资料被GameDeveloper Conference作为其物理教程的一部分收录,你可以从box2d.org下载中心获取相关的教程。

Box2DC++开发而成,因此你需要有一定的C++开发经验。Box2D不应该成为你的第一个C++项目!你应该能够熟练地编译,链接和调试项目。

1.3关于这篇指南

这篇指南覆盖了Box2D中的大部分程序接口,但是不可能面面俱到。我们希望读者能够通过随Box2D一同发布的测试工程做进一步学习。Box2D代码的注释遵循Doxygen定义的规范,所以很容易生成API文档。

指南随新的Box2D Release而更新,所以指南中的代码实际上已经和最新代码不完全一致了。

1.4问题反馈

如果你遇到任何问题或者有任何其他的反馈建议,请到论坛中留言,论坛同样也是一个大家交流讨论的好地方。Box2D的问题通过Googlecode project进行跟踪讨论,这种方式保证了你的问题不会在论坛中被冲掉。如果遇到bug或者有新的需求,请在这里留言:http://code.google.com/p/box2d

如果你能够提供足够多的细节,你的问题一定会很快被解决,如果能够提供一个能够重现问题的测试工程是再好不过了。在阅读完本文后,你可以进一步对测试工程做一些了解。

1.5核心概念

Box2D由几个基本概念和元素组成,这里我们简单做一些介绍,后面会详细展开每一部分:

形状(shape

一个形状是一个2D的几何物体,例如一个圆形或多边形。

刚体(rigid body

一块坚硬的物质,刚体上任何两点之间的距离都是定值。他们就像金刚石那样坚硬。在后面的讨论中我们用物体(object)来代替刚体。

装置(fixture

一个装置用来将一个形状和一个物体进行绑定,并且将一些材料特性(例如密度,摩擦力,弹性等)赋予物体。装置将形状添加到碰撞系统(collision system)中使其能够与其他形状进行碰撞。

约束(constraint

约束是一种物理连接,用来消除物体的自由度。一个2D的物体具有3个自由度(两个方向的移动和旋转)。如果我们将一个物体钉在墙上(像钟摆那样),那么我们就把它约束到了墙上,它就只能绕着钉子做旋转,所以我们通过这个约束消除了它的两个自由度。

接触约束(contact constraint

一种用来防止穿透刚体并模拟摩擦和弹性的特殊约束。你不需要创建接触约束,它们自动被Box2D创建。

关节(joint

关节是一种用来将两个或多个物体固定到一起的约束,Box2D支持多种约束类型:旋转(revolute),棱柱(prismatic),距离(distance)等等。其中一些类型的约束还可以具有限制(limit)和马达(motor)属性。

关节限制(joint limit

关节限制限定了一个关节的活动范围。例如,人的胳膊肘只能允许一定角度的转动。

关节马达(joint motor

关节马达能够根据关节的自由度来驱使连接的物体运动。例如,你可以使用马达来驱使胳膊肘左旋转。

世界(world

一个物理世界是一系列物体,装置和约束相互作用的集合。Box2D支持创建多个世界,但是通常我们不需要也不希望这么做。

解析器(solver

物理世界中的解析器用来加速时间和解析约束和关节约束。Box2D解析器是一个高效的迭代解析器(时间复杂度为NN为约束个数)。

持续碰撞(continuous collision

解析器通过使用离散的时间片来加速物体,没有连续碰撞的支持,就会导致高速物体穿过刚体表面(tunneling)。


Box2D用专门的算法来处理穿过(tunneling)。首先,碰撞算法可以介入到两个物体的运动中,找到第一次冲撞的时间点。接着,算法通过一个sub-stepping解析器将物体移动到第一次碰撞的时间点,然后处理碰撞。

1.6模块

Box2D由三个模块组成:公共模块(Common),碰撞模块(Collision)和动态模块(Dynamics)。公共模块负责处理诸如分配释放(allocation),数学计算(math)和设置(settings)。碰撞模块负责定义形状(shape),broad-phase(一种基于动态树算法的处理碰撞算法)和碰撞函数/查询。动态模块则负责模拟世界,物体,装置和关节。


1.7单位

浮点数适用于Box2D,容差(tolerance)的应用使Box2D模拟效果更好。对于“米-千克-秒”(MKS)这些单位,容差计算效果很好,尤其是当移动的形状大小在0.1米到10米之间时,Box2D的模拟效果很理想。这就意味着小到汤匙,大到汽车都可以很好地进行模拟。长度在50米以内的静态物体(staticshape)模拟效果很好。

作为一款2D物理引擎,使用像素(pixel)作为单位是非常有诱惑力的。不幸的是这常常导致不理想的模拟效果,甚至出现奇怪的现象。一个200像素的的物体很可能被Box2D当做45层楼高的物体。

我们可以把Box2D的物品当做移动广告牌来看,这个广告牌看起来是在一个以米为基本单位的世界中移动,但是你可以将它的坐标通过适当的比例转换为像素坐标,然后你就可以通过像素坐标来对你的精灵(sprite)元素进行布局等操作。你也可以做坐标反转。

Box2D中使用弧度(1弧度=180/π度)来计算角度,物体的旋转角就是用弧度来表示的,旋转角度可以无限增大。当物体的旋转角过大的时候,建议使用b2Body::SetAngle方法来重设旋转角。

1.8工厂和定义

快速内存管理在Box2D API中扮演着重要角色,当你创建一个b2Body或者b2Joint时,你需要使用b2World中提供的工厂函数。永远也不要尝试去用其他方式去为这些对象分配空间。

下面是创建方法:

b2Body* b2World::CreateBody(const b2BodyDef* def)

b2Joint* b2World::CreateJoint(const b2JointDef* def)

下面是对应的析构方法:

void b2World::DestroyBody(b2Body* body)

void b2World::DestroyJoint(b2Joint* joint)

当你创建一个物体或者关节时,你需要提供一个定义对象(Def),这些定义对象包含所有创建过程需要提供的信息。通过这种方式我们可以避免很多构造错误,使构造方法的参数尽可能少,提供合理的缺省值,减少访问器(accessor)的数量。

由于装置(形状)必须作为body的父对象,因此他们需要b2Body提供的工厂方法来创建和销毁:

b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def)

void b2Body::DestroyFixture(const b2Fixture* fixture)

还有一个通过形状和密度来创建装置的捷径:

b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float32density)

工厂方法不保留(retain)定义(definition)对象的引用,因此你可以在栈上创建他们并将他们视为临时资源。


86 0