【amazing cocos2d-x 3.0之十二】使用物理引擎完成弹球

来源:互联网 发布:海康威视网络键盘 编辑:程序博客网 时间:2024/05/17 23:44

在cocos2d-x 3.0中,我们应该如何使用新版的物理引擎呢?我们将采用一个简单的例子:有一个篮球,你可以通过旋转你的手机来改变重力的方向,同时篮球碰到屏幕边界可以反弹。下面是例子的效果图:



接下来,我们将来详细讲解。


1. 新建一个空的工程


新建一个工程,名为“Box2dBall”。将HelloWorld模板里面的内容都删除掉,HelloWorldScene.h替换成下面的代码:

#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"USING_NS_CC;class HelloWorld : public cocos2d::Layer{public:Sprite* _ball;PhysicsWorld* m_world;void setPhyWorld(PhysicsWorld* world){ m_world = world; };    // there's no 'id' in cpp, so we recommend returning the class instance pointer    static cocos2d::Scene* createScene();    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone    virtual bool init();          // implement the "static create()" method manually    CREATE_FUNC(HelloWorld);};#endif // __HELLOWORLD_SCENE_H__


HelloWorldScene.cpp代码如下:

#include "HelloWorldScene.h"Scene* HelloWorld::createScene(){    // 'scene' is an autorelease object    auto scene = Scene::createWithPhysics();scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);    // 'layer' is an autorelease object    auto layer = HelloWorld::create();layer->setPhyWorld(scene->getPhysicsWorld());    // add layer as a child to scene    scene->addChild(layer);    // return the scene    return scene;}// on "init" you need to initialize your instancebool HelloWorld::init(){    //////////////////////////////    // 1. super init first    if ( !Layer::init() )    {        return false;    }        return true;}

2. 创建世界相关理论


cocos2d-x 3.0对物理系统进行了封装,开发过程中可不再纠结与box2d和chipmunk的接口。Physics integration大大方便了物理系统的使用。


通过createWithPhysics()方法创建一个带有物理效果的Scene,然后将需要添加物理效果的层加入其中:

auto scene = Scene::createWithPhysics();scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);auto layer = HelloWorld::create();layer->setPhyWorld(scene->getPhysicsWorld());scene->addChild(layer);

3. 开启DebugDraw


DebugDraw对需要使用物理系统的我们来说是个很有用的方法。它可将碰撞体的形状、关节等等全部绘制出来,方便我们观察物体及整个场景的可碰撞区域。

scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

4. 添加篮球精灵


在HelloWorldScene.h中添加成员变量:

Sprite *_ball;

然后在HelloWorldScene.cpp的init方法中添加如下代码:

auto visibleSize = Director::getInstance()->getVisibleSize();auto origin = Director::getInstance()->getVisibleOrigin();// Create sprite and add it to the layer_ball = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52));_ball->setPosition(Point(400,600));auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width / 2);_ball->setPhysicsBody(ballBody);this->addChild(_ball);auto edgeSp = Sprite::create();auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));edgeSp->setPhysicsBody(boundBody); this->addChild(edgeSp); edgeSp->setTag(0);this->setAccelerometerEnabled(true);

跟Box2d确实有很大的区别。3.0新的物理引擎接口为我们省去了很多麻烦。下面来详细介绍一下上面的代码。


首先,我们在屏幕中间加入一个精灵。

auto winSize = Director::getInstance()->getWinSize();_ball = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52));_ball->setPosition(Point(400, 600));this->addChild(_ball);

接下来,弹球添加刚体属性:首先定义一个刚体body

auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width / 2);_ball->setPhysicsBody(ballBody);

然后,我们创建world对象

auto edgeSp = Sprite::create();auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));edgeSp->setPhysicsBody(boundBody); this->addChild(edgeSp); edgeSp->setTag(0);

运行之后,你可以看到球会往下掉,碰到边界会有弹性效果。


5. 加速计控制


如果我们想要达到倾斜屏幕就可以让球朝着屏幕的某个方向运行的话,我们就需要添加加速计控制。

首先,在init方法里面添加如下代码:

this->setAccelerometerEnabled(true);

在HelloWorldScene.h中添加新方法:

virtual void onAcceleration(Acceleration* acc, Event* unused_event);

并在HelloWorldScene.cpp中具体实现:

void HelloWorld::onAcceleration(Acceleration* acc, Event* unused_event){    Vect gravity(-acc->y * 15, acc->x * 15);    m_world->setGravity(gravity);}







0 0
原创粉丝点击