#include
”
Box2D.h
”


#include
<
cstdio
>

//

//
这是盒子和小盒子的一个简单例子模拟使用Box2D的.

//
这里我们创造一个大地面箱子和一小动态

//
箱子.

int
main(
int
argc,
char
**
argv)

{

B2_NOT_USED(argc);

B2_NOT_USED(argv);

//
定义世界的大小。

//
如果钢体到达世界的边缘,但是它将会速度越来越慢直到休眠。

//
我们创建地面体。要创建它我们需要一个物体定义(body definition),通过物体定义我们来

//
指定地面体的初始位置。

b2AABB worldAABB;

worldAABB.lowerBound.Set(
–
100.0f
,
–
100.0f
);

worldAABB.upperBound.Set(
100.0f
,
100.0f
);


//
定义重力向量

b2Vec2 gravity(
0.0f
,
–
10.0f
);


//
是否休眠

bool
doSleep
=
true
;


//
建立一个世界对象.

b2World world(worldAABB, gravity, doSleep);


//
我们创建地面体。要创建它我们需要定义一个静态刚体(body definition),通过物体定义我们来

//
指定地面体的初始位置。

b2BodyDef groundBodyDef;

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


//
将物体定义传给世界对象来创建地面体。世界对象并不保存到物体定义的引用。地面体是作

//
为静态物体(static body)创建的,静态物体之间并没有碰撞,它们是固定的。当一个物体具有零质量的

//
时候 Box2D 就会确定它为静态物体,物体的默认质量是零,所以它们默认就是静态的

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


//
我们创建一个地面的多边形定义。我们使用 SetAsBox 简捷地把地面多边形规定为一个盒子

//
(矩形)形状,盒子的中点就位于父物体的原点上。

b2PolygonDef groundShapeDef;


//
SetAsBox 函数接收了半个宽度和半个高度,这样的话,地面盒就是 100 个单位宽(x 轴)以及

//
20 个单位高(y 轴)。Box2D 已被调谐使用米,千克和秒来作单位,

groundShapeDef.SetAsBox(
50.0f
,
10.0f
);


//
我们在地面体上创建地面多边形,以完成地面体

groundBody
->
CreateShape(
&
groundShapeDef);


//
现在我们已经有了一个地面体,我们可以使用同样的方法来创建一个动态物体。除了尺寸之外的主要

//
区别是,我们必须为动态物体设置质量性质。

//
首先我们用 CreateBody 创建物体

b2BodyDef bodyDef;

//
设置起始坐标

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

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


//
接下来我们创建并添加一个多边形形状到物体上。注意我们把密度设置为 1,默认的密度是 0。并

//
且,形状的摩擦设置到了 0.3。形状添加好以后,我们就使用 SetMassFromShapes 方法来命令物体通

//
过形状去计算其自身的质量。这暗示了你可以给单个物体添加一个以上的形状。如果质量计算结果为 0,

//
那么物体会变成真正的静态。物体默认的质量就是零

b2PolygonDef shapeDef;

//
动态刚体的大小

shapeDef.SetAsBox(
1.0f
,
1.0f
);


//
密度,密度默认为0为0时判断为静态钢体

shapeDef.density
=
1.0f
;


//
摩擦力

shapeDef.friction
=
0.3f
;


//
创建刚体

body
->
CreateShape(
&
shapeDef);

//
我也可以通过这个函数设置位置和角度

//
body->SetXForm(b2Vec2(0.0f,5.0f),0.3f);


//
以物体形状计算

body
->
SetMassFromShapes();


//
Box2D 中有一些数学代码构成的积分器(integrator),积分器在离散的时间点上模拟物理方程,它将

//
与游戏动画循环一同运行。所以我们需要为 Box2D 选取一个时间步,通常来说游戏物理引擎需要至少

//
60Hz 的速度,也就是 1/60 的时间步。你可以使用更大的时间步,但是你必须更加小心地为你的世界调

//
整定义。我们也不喜欢时间步变化得太大,所以不要把时间步关联到帧频(除非你真的必须这样做)。直截

//
了当地,这个就是时间步:

float32 timeStep
=
1.0f
/
60.0f
;

//
Box2D 中还有约束求解器(constraint solver)。约束求解器用于解决模拟中的所有

//
约束,一次一个。单个的约束会被完美的求解,然而当我们求解一个约束的时候,我们就会稍微耽误另

//
一个。要得到良好的解,我们需要迭代所有约束多次。建议的 Box2D 迭代次数是 10 次。你可以按自己

//
的喜好去调整这个数,但要记得它是速度与质量之间的平衡。更少的迭代会增加性能并降低精度,同样

//
地,更多的迭代会减少性能但提高模拟质量。这是我们选择的迭代次数:

int32 iterations
=
10
;


//
输出坐标以及角度

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

{

//
单个约束求解以1/60帧。每帧计算10次

world.Step(timeStep, iterations);


//
得到动态刚体的坐标以及角度

b2Vec2 position
=
body
->
GetPosition();

float32 angle
=
body
->
GetAngle();


printf(
”
%4.2f %4.2f %4.2f\n
”
, position.x, position.y, angle);

}


//
When the world destructor is called, all bodies and joints are freed. This can

//
create orphaned pointers, so be careful about your world management.

system(
”
pause
”
);

return
0
;