首先从HelloWorld.cpp的源码入手,看看Box2D大致如何使用的。
包含头文件:
#include <Box2D/Box2D.h>
#include <cstdio>
//其中 Box2D/Box2D.h 实际上是包含Common、Collision、Dynamics、Rope的头文件。
//可以看出Box2D目录下就是其核心源码。而其他目录则是些文档,第三方库。和测试例程。
//分析helloworld的main函数:
//helloworld例程创建一个大的地面盒和一个小的动态物体。
//box2d不负责图形部分的构建,所以这个例程没有图形,需要第三方的图形接口来创造,这里
//先不考虑图形问题
//b2Vec2 是二维的vector,属性为浮点数x,y,这里创建一个重力矢量,用来在后面创建“世界”
b2Vec2 gravity(0.0f, -10.0f);
//是否允许物体休眠,物体休眠后不需要再去模拟,减少计算。
bool doSleep = true;
//根据前两个参数创建“世界”对象。(该处在栈上建立的b2World对象)
b2World world(gravity, doSleep);
//定义一个地面体,并设定位置。实际上一个物体除了位置还可以设置其他参数,参考b2BodyDef的定义即可
//这里仅需设定地面的位置。
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, -10.0f);
//前面创建的“世界”里调用CreateBody方法来在世界里创建物体。
//参数类型为刚刚创建的b2BodyDef对象(参数应该为指针。所以这里取地址)
// b2BodyDef对象的意义在于,不用在创建物体时,输入一个一个具体参数。把参数封装起来。
//创建结束后,得到一个真正的地面体对象。
b2Body* groundBody = world.CreateBody(&groundBodyDef);
//做好的地面体上,只设定了位置,但是还需要其他属性(形状,密度等),下面开始丰富它
//创建一个多边形,这里只是形状,用来做为创建真正物体的参数使用
b2PolygonShape groundBox;
//多边形设定为一个盒子形状,50.0f, 10.0f为一半的宽和高。
groundBox.SetAsBox(50.0f, 10.0f);
//终于可以根据这些属性把地面体做出来了,后一个参数是密度,
//据说groundBox的中点位于groundBody原点,这个以后再验证吧。
groundBody->CreateFixture(&groundBox, 0.0f);
//又是一个b2BodyDef ,看来还要创建一个物体了。套路一样的
//物体类型是动态的,(若未设定,则默认为静态的。上一个物体就是。)
//设定位置,并最终创建一个物体,和上一个物体同。
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(0.0f, 4.0f);
b2Body* body = world.CreateBody(&bodyDef);
//物体设定了位置,但是还没设定形状,下面就是啦
//形状定义,不多说了
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(1.0f, 1.0f);
//Fixture的定义,可以理解为在物体的其他属性,因为目前物体只设定了位置。
//在这个位置上的固定物,才能称之为物体吧,不过我觉得这里命名为Fixture不太好。
//不过套路和上面一样,增加了一些其他属性。
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
//摩擦设置为0.3
fixtureDef.friction = 0.3f;
//和上一个物体一样,终于在上面做出形状啥的了。
body->CreateFixture(&fixtureDef);
//设定时间步,也就是1s钟走60步(step)。帧速过高,自然人物行动也会过快。
//一般来说设为60hz
//还有就是速率迭代次数和位置迭代次数,用来限制迭代次数,这个留后分析吧。
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
//前面建造那么多东西,终于开始游戏循环了。
for (int32 i = 0; i < 60; ++i)
{
//“世界“调用Step方法,每个循环调用一次,推动游戏的进行。可以称之为步。
//走的每一步是根据timeStep 时间步和迭代次数限制来进行的。
world.Step(timeStep, velocityIterations, positionIterations);
//由于没有图形界面。所以通过打印动态物体的” body“的位置和旋转角度来看效果
b2Vec2 position = body->GetPosition();
float32 angle = body->GetAngle();
printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
}
return 0;
}
效果如下图: