admin 管理员组文章数量: 894082
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时,所有body、fixture和joint的内存都会被释放。这能使你的工作变得更简单。然而,你应该将body,fixture或joint的指针都清零,因为它们已经无效了。
2.6 关于testbed
一旦你征服了HelloWorld,你应该开始看Box2D的testbed了。testbed是一个单元测试框架以及演示环境,这是一些它的特点:
l 可移动和缩放的摄像机
l 鼠标拣选动态body的shape
l 可扩展的测试集
l 通过图形界面选择测试,调整参数,以及设置调试绘图
l 暂停和单步模拟
l 文字渲染
本文标签: Box2D翻译
版权声明:本文标题:Box2D翻译 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1688191930h190217.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论