简介

学过之前的那些章节,你就能做出来一款好玩的小游戏了,可是当你试图做一款复杂的游戏,那游戏需要模拟现实世界的情境,比如模拟两个物体碰撞,模拟物体受到重力,你就不知道该怎么办了。别担心,本章就介绍物理引擎,让我们来探索一下如何合理的使用物理引擎!

是否需要使用物理引擎

当你的需求很简单时,就不要使用物理引擎。比如只需要确定两个对象是否有碰撞,结合使用节点对象的 update 函数和 Rect 对象的 containsPoint()intersectsRect() 方法可能就足够了。例如:

  1. void update(float dt)
  2. {
  3. auto p = touch->getLocation();
  4. auto rect = this->getBoundingBox();
  5. if(rect.containsPoint(p))
  6. {
  7. // do something, intersection
  8. }
  9. }

这种检查交集以确定两个对象是否有碰撞的方法,只能解决非常简单的需求,无法扩展。比如你要开发一个游戏,一个场景有 100 个精灵对象,需要判断它们互相是否有碰撞,如果使用这种方式那将非常复杂,同时性能消耗还会严重影响 CPU 的使用率和游戏运行的帧率,这游戏根本没法玩。

这个时候就需要物理引擎了,在模拟物理情景上,物理引擎的扩展性好,性能的消耗也低。像刚才提到的那个情景,使用物理引擎就能很好的解决。初次了解物理引擎的话,肯定会觉得很陌生,我们来看一个简单的例子,通过例子来介绍术语,或许会容易接受一些。

  1. // create a static PhysicsBody
  2. auto physicsBody = PhysicsBody::createBox(Size(65.0f , 81.0f ), PhysicsMaterial(0.1f, 1.0f, 0.0f));
  3. physicsBody->setDynamic(false);
  4. // create a sprite
  5. auto sprite = Sprite::create("whiteSprite.png");
  6. sprite->setPosition(Vec2(400, 400));
  7. // sprite will use physicsBody
  8. sprite->addComponent(physicsBody);
  9. //add contact event listener
  10. auto contactListener = EventListenerPhysicsContact::create();
  11. contactListener->onContactBegin = CC_CALLBACK_1(onContactBegin, this);
  12. _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

虽然上面这个例子已经很简单了,但你可能还是觉得它复杂得有点吓人?别害怕,仔细的分析一下,就会发现也没那么复杂。

代码流程:

  • PhysicsBody 对象创建
  • Sprite 对象创建
  • PhysicsBody 对象以组件的形式被添加到 Sprite 对象
  • 创建监听器以响应 onContactBegin() 事件保持耐心,一旦我们一步一步的去分析,慢慢的就能理解这个过程。