[置顶] 【amazing cocos2d-x 3.0之十六】新物理引擎,来谈谈chipmunk和Box2d

关于物理引擎,在3.0中有了全新的Physics integration,把chipmunk和Box2D封装到引擎内部,简化开发者的开发步骤。再也不用关心底层具体是用哪个物理引擎,也不用直接调用物理引擎的接口。

物理引擎和cocos2d-x进行了深度融合:

(1) 物理世界被融入到Scene中,即当创建一个场景时,就可以指定这个场景是否使用物理引擎。
(2) Node自带body属性,也就是sprite自带body属性。
(3) Cocos2d-x 3.0对物理引擎的Body(PhysicsBody),Shape(PhysicsShape),Contact(PhysicsContact),Joint    (PhysicsJoint),World(PhysicsWorld)进行了封装抽象,使用更       简单。
(4) 更简单的碰撞检测监听EventListenerPhysicsContact。


1. 创建带物理引擎的游戏工程


默认创建的工程已经支持物理引擎,内部默认使用chipmunk。当然,你也可以改为Box2D。但这并不对游戏开发产生影响。


2. 创建带物理世界的场景scene


我们来创建一个带物理世界的场景scene,并传递给child layer。

在HelloWorldScene.h中添加如下代码:

private:
    PhysicsWorld* m_world;

public:
    void setPhyWorld(PhysicsWorld* world){ m_world = world;}

在HelloWorldScene.cpp中的createScene方法中添加如下代码:

auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

auto layer = HelloWorld::create();
layer->setPhyWorld(scene->getPhysicsWorld());

(1)用Scene新的静态工厂方法createWithPhysics()来创建物理世界的scene。

(2)Scene的getPhysicsWorld()方法用来获取PhysicsWorld实例。

(3)PhysicsWorld的setDebugDrawMask()方法,在调试物理引擎中是很有用的,它把物理世界中不可见的shape,joint,contact可视化。当调试结束,游戏发布的时候,你需要把这个debug开关关闭。

(4)通过setPhyWorld()方法来传递PhysicsWorld给ChildLayer。一个scene只有一个PhysicsWorld,其下的所有layer共用一个PhysicsWorld实例。


3. 创建物理边界


我们知道物理世界中,所有物体受重力的影响。
物理引擎提供staticShape创建一个不受重力影响的形状,在Cocos2d-x 2.0中,我们需要了解物理引擎的staticShape相关的各种参数来完成边界设置。
在3.0中,PhysicsShape属于Node的一个属性,要设置PhysicsWorld的属性,都需要通过一个Node实例来中介传达。
下面的代码展示如何创建一个围绕屏幕四周的物理边界。

Size visibleSize = Director::getInstance()->getVisibleSize();
auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);
auto edgeNode = Node::create();
edgeNode->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
edgeNode->setPhysicsBody(body);
scene->addChild(edgeNode);

(1)PhysicsBody包含很多工厂方法,createEdgeBox创建一个矩形边界,参数含义依次是:

             矩形区域大小,这里设置为visibleSize。
             设置材质,可选参数,默认为PHYSICSBODY_MATERIAL_DEFAULT。
             边线宽度,可选参数,默认为1。

(2)然后我们创建一个Node,把刚才创建的body附加到Node上,并设置好Node的position为屏幕中心点。
(3)最后,把Node添加到scene。
(4)Node的addChild方法,在3.0中,有对物理body做处理,它会自动把node的body设置到scene的PhysicsWorld上去。
(5)PhysicsBody中的工程方法,针对参数设置的body大小,会自动创建对应的PhysicsBody和一个PhysicsShape,这也是通常情况下,直接使用物理引擎创建一个body需             要做的事情。3.0的Physics integration极大的简化了使用物理引擎的代码量


4. 创建受重力作用 sprite


在3.0中创建一个受重力作用的sprite其实不难。示例代码如下:

void HelloWorld::addNewSpriteAtPosition(Point p)
{
    auto sprite = Sprite::create("circle.png");
    sprite->setTag(1);
    auto body = PhysicsBody::createCircle(sprite->getContentSize().width / 2);
    sprite->setPhysicsBody(body);
    sprite->setPosition(p);
    this->addChild(sprite);
}

首先创建一个sprite,然后用PhysicsBody::createCircle创建一个圆形的body附加在sprite上。
整个过程和之前创建边界的过程是一致的。


5. 碰撞检测


cocos2d-x中,事件派发机制做了重构,所有事件均有事件派发器统一管理。物理引擎的碰撞事件也不例外,
下面的代码注册碰撞begin回调函数。

auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_2(HelloWorld::onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

(1)碰撞检测的所有事件由EventListenerPhysicsContact来监听,创建一个实例,然后设置它的onContactBegin回调函数,CC_CALLBACK_2是Cocos2d-x 3.0使用C++ 11的回调函数指针转换助手函数,由于onContactBegin回调有两个参数,所有这里使用CC_CALLBACK_2来做转换。

(2)_eventDispatcher是基类Node的成员,Layer初始化后就可直接使用。


注明:本篇文章参考自泰然网




你可能感兴趣的:(box2D,chipmunk,cocos2d-x3.0,新物理引擎)