一、创建物理世界

在cocos2d-x 3.0版本中,封装了方便模拟物理世界操作的一系列physicals类,在这之前一般是将box2d或者chipmunk集成到cocos2d-x中来。而现在,就方便多了,到底多简单?看看就知道。接下来就来实现一个简单的物理世界吧。

二、简单的例子 - hello Physicals world

首先创建一个场景:

PhyScene.h

#ifndef __PHY_SCENE_H__
#define __PHY_SCENE_H__


#include "cocos2d.h"

using namespace cocos2d;

class PhySceneDemo:public Layer{
public:
    virtual bool init();
    static Scene* scene();
    CREATE_FUNC(PhySceneDemo);
    void setPhyWorld(PhysicsWorld *phyworld){this->m_world=phyworld;}
    void PhySceneDemo::onTouchesEnded(const std::vector<Touch*>& touches, Event *event);

private:
    PhysicsWorld *m_world;

};

#endif

PhyScene.cpp

#include "PhyScene.h"

Scene* PhySceneDemo::scene(){
    auto scene = Scene::createWithPhysics();
    auto layer = PhySceneDemo::create();
    layer->setPhyWorld(scene->getPhysicsWorld());
    scene->addChild(layer);
    return scene;
}

bool PhySceneDemo::init(){

    if(!Layer::init()){
        return false;
    }

    Size visiableSize = Director::getInstance()->getVisibleSize();
    Point point = Director::getInstance()->getVisibleOrigin();
    edge = Sprite::create();

    auto body = PhysicsBody::createEdgeBox(visiableSize,PHYSICSBODY_MATERIAL_DEFAULT,3);
    edge->setPosition(Point(visiableSize.width/2,visiableSize.height/2));
    edge->setPhysicsBody(body);
    this->addChild(edge);
    edge->setTag(0);
    this->setTouchEnabled(true);

    return true;
}

void PhySceneDemo::onTouchesEnded(const std::vector<Touch*>& touches, Event *event){
    for(Touch *touch:touches){
        auto location = touch->getLocation();
        Sprite *sprite = Sprite::create("hero_00.png");
        sprite->setPosition(location);
        sprite->setTag(1);
        auto sbody = PhysicsBody::createBox(Size(31,32));
        sprite->setPhysicsBody(sbody);

        this->addChild(sprite);
    }

}

最后修改AppDelegate.cpp文件,将启动Scene设置成PhySceneDemo:

auto scene = PhySceneDemo::scene();
// run
director->runWithScene(scene);

通过以上代码便完成了具有物理效果的一个物理场景,是不是非常简单,最后看下运行效果,然后我们再解释关键代码的意思。

三、关键代码讲解

相信大家都看到上图的效果了,那么现在来具体讲解下前面程序中,是如何创建一个物理世界的。 首先还是创建了一个场景叫做PhyScene.h的头文件,其中大部分与普通场景的创建类似,比如自带的HelloWorld场景。只不过新增了一个PhysicsWorld *m_world 的私有成员变量和一个void setPhyWorld(PhysicsWorld *phyworld){this->m_world=phyworld;}成员函数。由于PhySceneDemo类其实是一个继承Layer的类,本身是没有PhysicsWorld的,PhysicsWorld是在Scene类中的,上面新增的这两个就是将Scene的PhysicsWorld传递到Layer中,是得Layer具有物理世界的性质。具体传递可以看PhyScene.cpp的scene成员函数的实现,里面有

layer->setPhyWorld(scene->getPhysicsWorld());

这样,Layer中就有了PhysicsWorld,然后可以让添加到Layer中的Sprite等节点具有物理特效。具体来看init实现中的:

edge = Sprite::create();
auto body = PhysicsBody::createEdgeBox(visiableSize,PHYSICSBODY_MATERIAL_DEFAULT,3);
edge->setPosition(Point(visiableSize.width/2,visiableSize.height/2));
edge->setPhysicsBody(body);
this->addChild(edge);

关键创建一个PhysicsBody对象,但是我们看到这里是用createEdgeBox创建的。而后面的onTouchesEnded函数中的又是使用createBox函数创建的,其实还有更多的创建方式。虽然都是返回PhysicsBody对象,但是效果不一样。举例说明前者,我们进入createEdgeBox函数实现可以看到:

 PhysicsBody* body = new PhysicsBody();
 if (body && body->init())
 {
    body->addShape(PhysicsShapeEdgeBox::create(size, material, border, offset));
    body->_dynamic = false;
    body->autorelease();
    return body;
 }

其实在创建PhysicsBody对象的同时,会给他赋予Shape属性和其它一些属性,这里是一个PhysicsShapeEdgeBox,从名称可以看到是一个边缘盒子模型(物理世界的边缘)。最后设置精灵对象的PhysicsBody属性为之前的body对象,这样这个精灵就成为了一个物理世界的精灵。

总结

简单介绍了如何使用texturepacker并在cocos2d-x中创建精灵动画。

##文档信息