cocos2d-x有物理引擎吗
在Cocos2d-x 3.0中,我们可以使用新版的物理引擎。本文将通过制作一个简单的应用来介绍如何使用,该应用中有一个篮球,你可以通过旋转手机来改变重力的方向,同时篮球碰到屏幕边界会反弹。
本教程假设你已经学过前面的教程《如何使用Cocos2d-x 3.0来制作一个简单的iPhone游戏》,或者有同等相关经验。
好了,让我们开始学习物理引擎的使用吧!
创建一个空的工程
在Cocos2d-x - 3.0beta2的tools\project-creator目录下,执行create_project.py脚本来创建一个名为boxball的项目。如果你直接编译并运行该项目,会看到一个很酷的例子,它展示了Box2d的许多内容。不过,为了更好地理解范例的具体原理,我们将从0开始创建一个篮球反弹的应用。
首先,把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; };
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__
同时,修改HelloWorldScene.cpp文件:
#include "HelloWorldScene.h"
Scene* HelloWorld::createScene()
{
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
auto layer = HelloWorld::create();
layer->setPhyWorld(scene->getPhysicsWorld());
scene->addChild(layer);
return scene;
}
bool HelloWorld::init()
{
if (!Layer::init())
{
return false;
}
return true;
}
编译并运行项目,你会看到一个黑色的屏幕,这是一个空的项目。接下来,我们开始创建物理场景。
创建世界相关理论
Cocos2d-x - 3.0对物理系统进行了封装,在开发过程中,开发者无需再纠结于Box2d和Chipmunk的接口。这种物理集成(Physics integration)大大方便了物理系统的使用。如果你有兴趣,可以查看这篇文章:http://www.ityran.com/archives/5431。
我们可以通过createWithPhysics()方法创建一个带有物理效果的Scene,然后将需要添加物理效果的层加入其中,示例代码如下:
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
auto layer = HelloWorld::create();
layer->setPhyWorld(scene->getPhysicsWorld());
scene->addChild(layer);
开启DebugDraw
DebugDraw对于使用物理系统的开发者来说是一个非常有用的功能。它可以将碰撞体的形状、关节等信息全部绘制出来,方便我们观察物体及整个场景的可碰撞区域。开启DebugDraw的代码如下:
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
添加篮球精灵
首先,下载我制作的篮球图片,并将其添加到工程的Resources文件夹下。
接下来,在HelloWorldScene.cpp文件顶部添加以下代码,同时在HelloWorld类中添加成员变量Sprite *_ball;。
然后,在HelloWorldScene.cpp的init方法中加入以下代码:
auto visibleSize = Director::getInstance()->getVisibleSize();
auto origin = Director::getInstance()->getVisibleOrigin();
_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);
return true;
这段代码与Box2d有很大不同,Cocos2d-x 3.0新的物理引擎接口为我们省去了许多麻烦。下面我们逐步解释这段代码:
auto winSize = Director::getInstance()->getWinSize();
_ball = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52));
_ball->setPosition(Point(100, 100));
this->addChild(_ball);
首先,我们往屏幕中间加入一个精灵。如果你看了前面的教程,这里应该很容易理解。
auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width / 2);
_ball->setPhysicsBody(ballBody);
接下来为篮球添加刚体属性。我们定义一个刚体body,并将其设置给篮球精灵。
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);
然后,我们创建一个边界精灵,并为其添加刚体属性,使其成为一个边界。
编译并运行项目,你应该可以看到球会往下掉,碰到边界会有弹性效果。
完成加速计控制
如果我们可以通过倾斜屏幕让球朝着屏幕的某个方向运动,那将会非常棒。首先,我们需要在init方法里加入以下代码:
this->setAccelerometerEnabled(true);
然后,在HelloWorld类中添加新的方法:
virtual void onAcceleration(Acceleration* acc, Event* unused_event);
并完善该方法:
void HelloWorld::onAcceleration(Acceleration* acc, Event* unused_event)
{
Vect gravity(-acc->y * 15, acc->x * 15);
m_world->setGravity(gravity);
}
通过以上步骤,我们就完成了一个使用Cocos2d-x 3.0物理引擎的简单应用,你可以通过倾斜手机来控制篮球的运动方向。