cocos2d-x有物理引擎吗

2015年03月03日 11:23 0 点赞 0 评论 更新于 2025-11-21 16:36

在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.cppinit方法中加入以下代码:

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物理引擎的简单应用,你可以通过倾斜手机来控制篮球的运动方向。

作者信息

boke

boke

共发布了 3994 篇文章