这篇文章来讲如何创建物理世界。下面来看:
创建和摧毁物理世界:
//物理世界的重力
b2Vec2 gravity;
gravity.Set(0.0f,-10.0f);
//创建物理世界
world = new b2World(gravity);
//设置是否允许物体进入休眠状态
world->SetAllowSleeping(true);
//设置是否使用连续物理检测
world->setContinuousPhysics(true);
//摧毁物理世界
delete world;
world = NULL;
上述代码中使用两个函数来设置世界的运转状态:
(1)函数SetAllowSleeping(true)的作用是允许静止的物体进入休眠状态。在休眠状态下的物体将不会再参与物理运算。这是一种提升引擎运算性能的方法。
(2)函数setContinuousPhysics(true)的作用是设置引擎中的物理模拟是否使用连续检测的方式。连续检测的方式将会在更短的时间内进行物理模拟。这意味物理模拟的精度将会提高,同时会降低引擎的运行性能。
让世界运转起来:
物理世界类中用于驱动模拟的函数为Step,调用它时,需要指定一个时间步和一个速度及位置的迭代次数。例如下面代码所示:
//时间步,频率
float32 timeStep = 1.0f/60.0f;
//速度迭代
int32 velocityIterations = 10;
//位置迭代次数
int32 positionIterations = 8;
//驱动函数
myWorld->Step(timeStep,velocityIterations,positionIterations);
上述代码只是驱动物理世界执行一个时间步,开发者要将此段代码放在一个能够循环调用的函数当中。在时间步完成之后,我们就能获得物体和关节经过物理模拟后的信息。最常见的情况就是,游戏中的绘制引擎将会得到物体的位置和速度。这样才能更新游戏画面中的角色并渲染它们。但要注意的一点是:虽然驱动物理世界可以在游戏循环的任何地方,但应注意事情发展的先后顺序。另外,在物理引擎执行了一次时间步之后,最好是清除任何施加到物体之上的力。可以使用b2World::ClearForces去掉力的持续作用效果。
搜索世界(遍历世界):
经过前面的两步,我们已经创建了一个物理世界,然后使用驱动函数使它运转。游戏当中的物理世界就呈现在大家面前了。不过一个空无一物的世界对开发者来说没有意义。因为我们还没有创建物理世界中的对象。创建对象以后再讲,下面介绍的是如何搜索世界中的对象。
物理世界相当于一个容器,它会容纳工厂创建出来的所有对象。开发者可以通过遍历的方式来获取世界中的所有物体、框架和关节。下面这段代码会唤醒世界中的额所有物体:
//遍历物理世界中的物体
for(b2Body* b = myWorld->GetBodyList();b;b = b->GetNext())
{
//唤醒物体
b->WakeUp();
}
遍历销毁物体:
b2Body* node = myWorld->GetBodyList();
//遍历物理世界中的物体
while(node)
{
//获得物体
b2Body *b = node;
//获得下一个物体
node = node->GetNext();
//获得物体所代表精灵对象
CCSprite* myActor = (CCSprite*)b->GetUserData();
//判断精灵对象是否死亡
if(myActor->IsDead())
{
//销毁物体
myWorld->DestroyBody(b);
}
}
删除多个物体:
b2Body* node = myWorld->GetBodyList();
while(node)
{
//获得物体
b2Body *b = node;
//获得下一个物体
node = node->GetNext();
//获得物体所代表精灵对象
CCSprite* myActor = (CCSprite*)b->GetUserData();
//判断精灵对象是否死亡
if(myActor->IsDead())
{
//销毁多个物体
bool otherBodiesDestroyed = GameCrazyBodyDestroyer(b);
//重新获得物体指针
if(otherBodiesDestroyed)
{
node = myWorld->GetBodyList();
}
}
}
这里新增一个函数GameCrazyBodyDestroyer。它将会删除多个物理引擎中的物体。在删除操作之后,代码又重新调用了函数GetBodyList,这样就会重新获得物体链表的开始指针,因此就算删除多个物体,链表依旧没有被打断。还有另一种方法是将需要删除的物体暂存在一个临时容器当中,等物体链表遍历完成之后,就可以删除临时容器中的物体了。