Box2D翻译_第二章

本文是对Box2D v2.1.2 manual中文翻译(现在网上流行的一个中文翻译是针对以前版本的,跟最新的2.1.2版有些不对应)的第二章。持续更新中。。。。。。

 

 

 

2. Hello Box2D

Box2D的分发包里包含一个HelloWorld项目,它创建一个巨大的地面盒和一个小小的动态盒。代码中不包含任何图形。你总是在控制台看到盒子随时间而改变位置。

这是一个介绍怎样运行Box2D的很好例子。

2.1      创建world

每个Box2D程序都将从一个b2World对象的创建开始,这是一个管理内存、对象和模拟的物理中心。你可以从栈、堆或数据区中分配物理world。这是由你决定的。

创建Box2D world很简单。首先,定义重力因子。然后我们告诉world允许body在苏醒之前沉睡。沉睡中的body不需要任何模拟。

b2Vec2 gravity(0.0f, -10.0f);

bool doSleep = true;

现在我们创建world对象。注意,我们通常在栈上创建world

b2World world(gravity, doSleep);

那么现在我们有了自己的物理world,让我们再加些东西进去吧。

2.2      创建地面盒

物体通常由以下步骤来创建:

1、 使用位置(position),阻尼(damping)等定义body

2、 使用world对象创建body

3、 使用shape(形状)、friction(摩擦)、density(密度)等定义fixture

4、 body上创建fixture

第一步,我们创建地面体。要创建它我们需要一个物体定义(body definition),通过物体定义我们来指定地面体的初始位置。

b2BodyDef groundBodyDef;

groundBodyDef.position.Set(0.0f, -10.0f);

第二步,将物体定义传给world对象来创建地面体。world对象并不保存物体定义的引用。地面体是作为静态物体(static body)创建的,静态物体之间并没有碰撞,它们是固定的。当一个物体具有零质量的时候Box2D就会确定它为静态物体,物体的默认质量是零,所以它们默认就是静态的。

b2Body* groundBody = world.CreateBody(&groundBodyDef);

第三步,我们创建一个地面多边形。使用SetAsBox简捷地把地面多边形规定为一个盒子形状,盒子的中点就位于父body的原点上。

b2PolygonShape groundBox;

groundBox.SetAsBox(50.0f, 10.0f);

其中,SetAsBox函数接收半个宽度和半个高度,这样的话,地面盒就是100个单位宽(x)以及20个单位高(y)Box2D已被调整为使用米,千克和秒来做单位。所以你可以考虑用米作为长度单位。当物体具有真实世界中物体的大小时,Box2D通常工作良好。例如,一个桶约1米高。由于浮点算法的局限性,使用Box2D驱动冰河或沙尘的运动并不是一个好主意。

在第4步中通过创建shape fixture,我们结束地面盒的创建。在这步中有一个捷径,我们不需要修改默认fixture的材质属性,所以可以直接把shape传递给body而不用创建fixture定义。在后面的介绍中,我们将会看到如何使用fixture定制材质属性。

groundBody->CreateFixture(&groundBox);

Box2D不保存shape的引用。它把数据克隆到一个新的b2Shape对象中。

注意,每个fixture都必须有一个父body,即使fixture是静态的。然而,你可以把所有静态fixture都依附于单个静态body之上。这个静态物体是为了保证Box2D内部的代码更具一致性,以减少潜在的bug数量。

大多Box2D类型以b2为前缀。这是这是为了减少与你的代码之间命名冲突的情况。

2.3      创建动态body

现在,我们已经有了一个地面体。我们可以使用同样的方法来创建一个动态body。除了尺寸之外的主要区别是我们必须为动态body设置质量属性。

首先,我们使用CreateBody方法创建body。默认情况下body是静态的,所以我们应当在构造期间设置b2BodyType,使得body变为动态的。

b2BodyDef bodyDef;

bodyDef.type = b2_dynamicBody;

bodyDef.position.Set(0.0f, 4.0f);

b2Body* body = world.CreateBody(&bodyDef);

然后,我们使用fixture定义创建并添加一个多边形形状到物体上。我们先创建一个box shape

b2PolygonShape dynamicBox;

dynamicBox.SetAsBox(1.0f, 1.0f);

接下来我们使用box创建一个fixture定义。值得注意的是,我们把密度设置为1,默认的密度是0。而且,shape的摩擦设置为0.3

b2FixtureDef fixtureDef;

fixtureDef.shape = &dynamicBox;

fixtureDef.density = 1.0f;

fixtureDef.friction = 0.3f;

我们使用fixture定义可以创建fixture。这会自动更新body的质量。你可以为body添加许多fixture。每个fixture对总质量都有贡献。

body->CreateFixture(&fixtureDef);

这就是初始化过程。现在我们已经准备好开始模拟了。

2.4      模拟(Box2D的)世界

我们已经初始化了地面盒和动态盒。现在是让牛顿接手的时刻了。我们只有少数几个问题需要考虑。

Box2D使用数学算法中的积分器(integrator)。积分器在离散的时间点上模拟物理方程,它将与传统游戏动画循环一同运行。所以我们需要为Box2D选取一个时间步,通常来说游戏的物理引擎需要至少要60Hz的速度,也就是1/60s的时间步。你可以使用更大的时间步,但是你必须更加小心地为你的世界调整定义。我们也不喜欢时间步变化得太大,所以不要把时间步关联到帧频(除非你真的必须这样做)。直截了当地,这就是时间步:

float32 timeStep = 1.0f / 60.0f;

除了积分器之外,Box2D中还有更大段代码称为约束求解器(constraint solver)。约束求解器用于解决模拟中的所有约束,一次一个。单个的约束会被完美的求解,然而当我们求解一个约束的时候,我们就会稍微破坏另一个。要得到好的解,我们需要迭代所有约束多次。

在约束求解器中有两个相位:速度相位和位置相位。在速度相位中,求解器计算使得body运动的脉冲。在位置相位中,求解器调整body的位置以减少重叠和关节脱离。每个相位拥有自己的迭代计数。此外,如果错误小的话,位置相位可能早期退出迭代。

对于速度和位置两者而言,建议的Box2D迭代次数是10次。你可以按自己的喜好去调整这个数字,但要记得它是速度与精度之间的折中。更少的迭代会增加性能并降低精度,同样地,更多的迭代会降低性能但提高模拟质量。对于这个简单示例,我们不需要更多迭代。这是我们选择的迭代次数。

int32 velocityIterations = 6;

int32 positionIterations = 2;

注意,时间步和迭代次数是完全无关的。一次迭代不是一个子步。一次迭代就是在时间步之内单次遍历所有约束。你可以在单个时间步内多次遍历约束。

现在我们可以开始模拟循环了,在游戏中模拟循环应该并入游戏循环。每次循环你都应该调用b2World::Step。通常调用一次就够了,这取决于帧频以及物理时间步。步进后,你应当调用b2World::ClearForces清除你施加到body上的任何力。

这个Hello World程序设计得非常简单,所以它没有图形输出。胜于完全没有输出,代码会打印出动态body的位置以及旋转角度。这是在1秒钟时间内模拟60个时间步的模拟循环。

for (int32 i = 0; i < 60; ++i)

{

world.Step(timeStep, velocityIterations, positionIterations);

world.ClearForces();

b2Vec2 position = body->GetPosition();

float32 angle = body->GetAngle();

printf("%4.2f %4.2f %4.2f/n", position.x, position.y, angle);

}

输出展示了盒子降落到地面盒的情况。你的输出应当看起来是这样:

0.00 4.00 0.00

0.00 3.99 0.00

0.00 3.98 0.00

...

0.00 1.25 0.00

0.00 1.13 0.00

0.00 1.01 0.00

2.5      清理工作

当一个world对象超出它的作用域,或通过指针将其delete时,所有bodyfixturejoint的内存都会被释放。这能使你的工作变得更简单。然而,你应该将bodyfixturejoint的指针都清零,因为它们已经无效了。

2.6      关于testbed

一旦你征服了HelloWorld,你应该开始看Box2Dtestbed了。testbed是一个单元测试框架以及演示环境,这是一些它的特点:

l  可移动和缩放的摄像机

l  鼠标拣选动态bodyshape

l  可扩展的测试集

l  通过图形界面选择测试,调整参数,以及设置调试绘图

l  暂停和单步模拟

l  文字渲染

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值