Instance introduction box2d physical engine in Cocos2d-x: hellobox2d

Source: Internet
Author: User
我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用Box2D物理引擎的开发过程,熟悉这些API的使用。这个实例运行后的场景,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一个新的精灵,精灵的运行自由落体运动。
  



HelloBox2D实例使用Box2D引擎进行开发过程,12-15所示。下面我们就按照这个步骤介绍一下代码部分。首先看一下看HelloWorldScene.h文件,它的代码如下:
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"#include "Box2D/Box2D.h"①#define PTM_RATIO 32②class HelloWorld : public cocos2d::Layer{b2World* world;③public:    static cocos2d::Scene* createScene();    virtual bool init();  virtual void update(float dt);④virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event); ⑤    CREATE_FUNC(HelloWorld);void initPhysics();⑥void addNewSpriteAtPosition(cocos2d::Vec2 p);⑦};#endif // __HELLOWORLD_SCENE_H__


上述第①行代码#include "Box2D/Box2D.h"是引入使用Box2D引擎需要头文件。第②行代码#define PTM_RATIO 32是定义宏PTM_RATIO,PTM_RATIO是屏幕上多少像素为1米,32表示屏幕上32像素表示1米,在Box2D中单位使用MKS公制系统,即:长度单位采用米,质量单位采用千克,时间单位采用秒。
代码第③行world是声明物理世界b2World成员变量。第④行代码是游戏循环函数。第⑤行代码是触摸点击响应函数。第⑥行代码是声明初始化物理引擎函数initPhysics。第⑦行是声明addNewSpriteAtPosition函数,是在触摸点创建一个精灵对象。
HelloWorldScene.cpp中HelloWorld::init()函数代码如下:
bool HelloWorld::init(){if ( !Layer::init() ){return false;}Size visibleSize = Director::getInstance()->getVisibleSize();Vec2 origin = Director::getInstance()->getVisibleOrigin();// 初始化物理引擎this->initPhysics();①setTouchEnabled(true);//设置为单点触摸setTouchMode(Touch::DispatchMode::ONE_BY_ONE);//开始游戏循环scheduleUpdate();②return true;}


上述代码第①行调用initPhysics()函数初始化物理引擎。第②行代码scheduleUpdate()是开始游戏循环,一旦开启游戏循环就会回调HelloWorld::update(float dt)函数。
HelloWorldScene.cpp中初始化物理引擎HelloWorld::initPhysics()函数代码如下:
void HelloWorld::initPhysics(){Size s = Director::getInstance()->getVisibleSize();//重力参数b2Vec2 gravity; ①gravity.Set(0.0f, -10.0f); ②//创建世界world = new b2World(gravity); ③// 允许物体是否休眠world->SetAllowSleeping(true);④// 开启连续物理测试world->SetContinuousPhysics(true);⑤//地面物体定义b2BodyDef groundBodyDef;⑥//左下角groundBodyDef.position.Set(0, 0);⑦//创建地面物体b2Body* groundBody = world->CreateBody(&groundBodyDef);⑧//定义一个有边的形状b2EdgeShape groundBox;⑨// 底部groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));⑩//使用夹具固定形状到物体上groundBody->CreateFixture(&groundBox,0);?// 顶部groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));groundBody->CreateFixture(&groundBox,0);// 左边groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));groundBody->CreateFixture(&groundBox,0);// 右边groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0)); groundBody->CreateFixture(&groundBox,0);}


代码第①行b2Vec2 gravity是声明重力变量,b2Vec2是一个二维矢量,它的两个属性为浮点数x和y,表示在x轴和y轴方向的矢量。第②行代码gravity.Set(0.0f, -10.0f)是设置矢量值,其中(0.0f, -10.0f)表示只有重力作用物体,-10.0f表示沿着y轴向下。
第③行代码world = new b2World(gravity)是创建物理世界b2World对象,这里采用了new创建物理世界对象,在C++中new关键字分配内存,释放内存是delete关键字。World是成员变量,需要自己释放成员变量一般是在析构函数中释放,代码如下:
HelloWorld::~HelloWorld()
{
    CC_SAFE_DELETE(world); 
}
其中CC_SAFE_DELETE(world)是安全释放world变量,CC_SAFE_DELETE宏代表安全释放内存。
第④行代码world->SetAllowSleeping(true)是允许物体睡眠与否,如果允许休眠,可以提高物理世界中物体的处理效率,只有在发生碰撞时才唤醒该对象。
第⑤行代码world->SetContinuousPhysics(true)是开启连续物理测试[ 开启连续物理测试,这是因为计算机只能把一段连续的时间分成许多离散的时间点,再对每个时间点之间的行为进行演算,如果时间点的分割不够细致,速度较快的两个物体碰撞时就可能会产生“穿透”现象,开启连续物理将启用特殊的算法来避免该现象。]。
第⑥行代码是声明形状定义(b2BodyDef)变量。第⑦行代码groundBodyDef.position.Set(0, 0)是设置形状的位置。第⑧行代码b2Body* groundBody = world->CreateBody(&groundBodyDef)是通过形状定义变量groundBodyDef创建地面物体。
第⑨行代码是声明一个有边形状定义b2EdgeShape变量,第⑩行代码groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0))是设置有边形状的开始位置(0,0)和结束位置(s.width/PTM_RATIO,0),s.width/PTM_RATIO是将像素换算成米。第?行代码是使用夹具固定形状到物体上。用类似的函数定义顶部、左边和右边的物体。
HelloWorldScene.cpp中创建精灵HelloWorld::addNewSpriteAtPosition函数代码如下:
void HelloWorld::addNewSpriteAtPosition(Vec2 p){    log("Add sprite %0.2f x %02.f",p.x,p.y);//创建物理引擎精灵对象auto sprite = Sprite::create("BoxA2.png");①sprite->setPosition( Vec2( p.x, p.y) );this->addChild(sprite);//物体定义b2BodyDef bodyDef;②bodyDef.type = b2_dynamicBody;③bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);④b2Body *body = world->CreateBody(&bodyDef);⑤body->SetUserData(sprite);⑥// 定义2米见方的盒子形状b2PolygonShape dynamicBox;⑦dynamicBox.SetAsBox(1, 1);⑧// 夹具定义b2FixtureDef fixtureDef;⑨//设置夹具的形状fixtureDef.shape = &dynamicBox;⑩//设置密度fixtureDef.density = 1.0f;?//设置摩擦系数fixtureDef.friction = 0.3f;?//使用夹具固定形状到物体上body->CreateFixture(&fixtureDef);?}


上述代码第①行是创建精灵(Sprite)对象,精灵(Sprite)对象与物理引擎物体是没有关系,我们需要在游戏循环函数中更新。
代码第②行是声明动态物体定义变量,代码第③行bodyDef.type = b2_dynamicBody是设置物体类型为动态物体,物体分为静态和动态物体。第④行代码是设置物体的位置,它的单位是米。第⑤行代码b2Body *body = world->CreateBody(&bodyDef)是创建物体对象。第⑥行代码body->SetUserData(sprite)是将精灵放置到物体的UserData属性中,这样便于我们从物体中获取相关联的物体。
第⑦行代码b2PolygonShape dynamicBox是声明多边形形状定义变量。第⑧行代码dynamicBox.SetAsBox(1, 1)是设置多边形为矩形盒子形状,由于坐标原点在盒子的左下角,SetAsBox是设置盒子的中心为(1,1),那么这个盒子的就是2米见方的大小。
第⑨行代码是b2FixtureDef fixtureDef是声明夹具定义变量。第⑩行代码是设置夹具的形状。第?行代码fixtureDef.density = 1.0f是设置形状的密度。第?行代码fixtureDef.friction = 0.3f是设置摩擦系数,范围是0.0~1.0之间。第?行代码body->CreateFixture(&fixtureDef) 是使用夹具固定形状到物体上,这样物体就有了形状。
HelloWorldScene.cpp中游戏循环函数HelloWorld::update代码如下:
void HelloWorld::update(float dt){float timeStep = 0.03f; int32 velocityIterations = 8;int32 positionIterations = 1;world->Step(timeStep, velocityIterations, positionIterations);for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())①{if (b->GetUserData() != nullptr) {Sprite* sprite = (Sprite*)b->GetUserData();sprite->setPosition( Vec2( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );sprite->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );}}②}


其中代码①~②这段代码可以同步物理引擎中的物体与精灵位置和状态。



更多内容请关注国内第一本Cocos2d-x 3.2版本图书《Cocos2d-x实战:C++卷》本书交流讨论网站:http://www.cocoagame.net
更多精彩视频课程请关注智捷课堂Cocos课程:http://v.51work6.com
欢迎加入Cocos2d-x技术讨论群:257760386

欢迎关注智捷iOS课堂公共平台


实例介绍Cocos2d-x中Box2D物理引擎:HelloBox2D

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.