|   版权声明:本文为博主原创文章,未经博主允许不得转载。

  在很多的游戏设计中一般都会涉及和模拟到真实的物理世界。然而游戏中模拟真实世界的物理会很复杂。使用已经写好的物理引擎会用很大的帮助和便利。 Box2D的和Chipmunk是两个著名的物理引擎,在Cocos2d-x引擎中已经很好的集成它们。在Cocos2d-x v2的开发人员需要直接使用物理引擎。 Cocos2d-x提供了一个简单的类:CCPhysicsSprite,以帮助缩小使用差距,但对于其它元素的开发者需要直接调用物理引擎的API。

  在Cocos2d-x V3+ 版本事情发生了变化。Cocos2d-x V3+ 版本集成了全新的物理引擎,基于Chipmunk的核心API。开发人员不再需要关心它的物理引擎将被用于或需要直接调用物理引擎的API。

  这节我们将介绍一下Box2D物理引擎:

  Box2D是一个用于游戏的2D刚体仿真库。Cocos2d-x程序员可以使用它在他们的游戏使物体的运动方式,使可信的游戏世界更互动。采用Box2D来模拟真实的物理世界的过程其实就是一句话:这个过程与上帝创建世界的过程类似,上帝首先创建了世界,然后在为世界指定了边界,否则万物就会掉到世界之外的混沌里去了,最后上帝在继续的创建了万物(这是网上的一句很适合形容Box2D创建物理世界的话)。

  下面就根据上面的上帝创建世界的构成来创建游戏中的物理世界:

  (1)、首先创建了世界(其实就是初始化物理世界,并且设置此物理世界的一些特性)

  (2)、指定物理世界的边界

  (3)、创建万物(即创建动态或者静态的Body)

  (4)、当我们将上面的物理世界全部创建完之后,我们发现创建的刚体并不能运动。其实是我们没有更新刚体的位置。因此我们应该写一个定时器: update来时时更新Body的信息。

  (5)、然后我们在初始化场景的init()函数中,启动定时器即可。下面解释上面的部分代码:

    >.SetAllowSleeping():是否允许物体睡眠,休眠状态(true),可以提高物理世界中物体的处理效率,只在发生碰撞时才唤醒该对象。

    >.gravity.Set(0.0f, -10.0f)是设置矢量值,其中(0.0f, -10.0f)表示只有重力作用物体,-10.0f表示沿着y轴向下,如果在x轴方向‘-’表示沿x轴向左。

    >.world->SetContinuousPhysics(true):是开启连续物理测试,[开启连续物理测试,这是因为计算机只能把一段连续的时间分成许多离散的时间点,再对每个时间点之间的行为进行演算,如果时间点的分割不够细致,速度较快的两个物体碰撞时就可能会产生“穿透”现象,开启连续物理将启用特殊的算法来避免该现象。]。

代码 1:(动态物体自由落体运动)

HelloWorld.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
{
private:
b2World* world;
public:
static cocos2d::Scene* createScene(); virtual bool init(); virtual void update(float dt);
virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld); void initPhysics();
void createland();
void addNewSprite(cocos2d::Vec2 point);
}; #endif // __HELLOWORLD_SCENE_H__ HelloWorld.cpp #include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create(); // 'layer' is an autorelease object
auto layer = HelloWorld::create(); // add layer as a child to scene
scene->addChild(layer); // return the scene
return scene;
} // on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
} auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto sprite = Sprite::create("HelloWorld.png");
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
this->addChild(sprite, 0); //初始化物理引擎
this->initPhysics();
this->createland(); setTouchEnabled(true);
setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
//开始游戏循环
scheduleUpdate(); return true;
} void HelloWorld::initPhysics()
{
//重力参数
b2Vec2 gravity;
gravity.Set(0.0f, -9.8f);
//创建世界
world = new b2World(gravity);
//是否允许物体休眠
world->SetAllowSleeping(true);
//开启连续的物理测试
world->SetContinuousPhysics(true);
} void HelloWorld::addNewSprite(Vec2 point)
{
//创建物理引擎的精灵对象
auto sprite = Sprite::create("CloseNormal.png");
sprite->setPosition(Vec2(point.x, point.y));
this->addChild(sprite);
//刚体定义
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(point.x / PTM_RATIO,
point.y / PTM_RATIO);
b2Body* body = world->CreateBody(&bodyDef);
body->SetUserData(sprite);
//定义盒子
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.6, 0.6);
//夹具
b2FixtureDef fixtureDef;
//设置夹具的形状
fixtureDef.shape = &dynamicBox;
//设置密度
fixtureDef.density = 1.0f;
//设置摩擦系数
fixtureDef.friction = 0.3f;
//使用夹具固定形状到物体上
body->CreateFixture(&fixtureDef);
} void HelloWorld::update(float dt)
{
world->Step(dt, 8, 1);
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(0);
}
}
} bool HelloWorld::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event)
{
Touch *t = touch;
Vec2 point = t->getLocationInView();
point = Director::getInstance()->convertToGL(point);
this->addNewSprite(point);
return false;
} void HelloWorld::createland()
{
Size s = Director::getInstance()->getVisibleSize();
//地面物体定义
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);
}

代码 2:(动态物体上升移动)

HelloWorld.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
{
protected:
b2World* world;
cocos2d::Sprite* sprite;
b2Body* body;
public:
static cocos2d::Scene* createScene(); virtual bool init(); virtual void update(float dt);
virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld); void initPhysics();
void createLand();
void addNewSprite();
}; #endif // __HELLOWORLD_SCENE_H__ HelloWorld.cpp #include "HelloWorldScene.h"
#include "SimpleAudioEngine.h" USING_NS_CC; Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create(); // 'layer' is an autorelease object
auto layer = HelloWorld::create(); // add layer as a child to scene
scene->addChild(layer); // return the scene
return scene;
} // on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
} auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto sprite = Sprite::create("HelloWorld.png");
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
this->addChild(sprite, 0); //初始化物理引擎
this->initPhysics();
this->createLand();
addNewSprite();
setTouchEnabled(true);
setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
//开始游戏循环
scheduleUpdate(); return true;
} void HelloWorld::initPhysics()
{
//重力参数
b2Vec2 gravity;
gravity.Set(0.0f, -9.8f); //创建世界
world = new b2World(gravity); //是否允许物体休眠
world->SetAllowSleeping(true);
//开启连续的物理测试
world->SetContinuousPhysics(true);
} void HelloWorld::addNewSprite()
{
//创建物理引擎的精灵对象
sprite = Sprite::create("CloseNormal.png");
sprite->setPosition((Director::getInstance()->getVisibleSize().width / 3) * 3,
Director::getInstance()->getVisibleSize().height);
this->addChild(sprite); //刚体定义
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(sprite->getPosition().x / PTM_RATIO,
sprite->getPosition().y / PTM_RATIO);
body = world->CreateBody(&bodyDef);
body->SetUserData(sprite); //定义2米见方的盒子
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.6, 0.6); //夹具
b2FixtureDef fixtureDef;
//设置夹具的形状
fixtureDef.shape = &dynamicBox;
//设置密度
fixtureDef.density = 1.0f;
//设置摩擦系数
fixtureDef.friction = 0.3f;
//使用夹具固定形状到物体上
body->CreateFixture(&fixtureDef);
} void HelloWorld::update(float dt)
{
world->Step(dt, 8, 1);
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(0);
}
}
} bool HelloWorld::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event)
{
//Touch *t = touch;
//Vec2 point = t->getLocationInView();
//point = Director::getInstance()->convertToGL(point);
//点击一次屏幕,小球上升5个像素点
body->SetLinearVelocity(b2Vec2(0, 5)); return false;
} void HelloWorld::createLand()
{
Size s = Director::getInstance()->getVisibleSize(); //地面物体定义
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);
}

代码 3:(漂浮物体横向移动)

HelloWorld.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
{
protected:
b2World* world;
cocos2d::Sprite* sprite;
b2Body* body;
public:
static cocos2d::Scene* createScene(); virtual bool init(); virtual void update(float dt);
virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld); void initPhysics();
void createLand();
void addNewSprite();
}; #endif // __HELLOWORLD_SCENE_H__ HelloWorld.cpp #include "HelloWorldScene.h"
#include "SimpleAudioEngine.h" USING_NS_CC; Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create(); // 'layer' is an autorelease object
auto layer = HelloWorld::create(); // add layer as a child to scene
scene->addChild(layer); // return the scene
return scene;
} // on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if (!Layer::init())
{
return false;
} auto visibleSize = Director::getInstance()->getVisibleSize();
auto origin = Director::getInstance()->getVisibleOrigin(); auto sprite = Sprite::create("HelloWorld.png");
sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
this->addChild(sprite, 0); //初始化物理引擎
this->initPhysics();
this->createLand();
addNewSprite();
setTouchEnabled(true);
setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
//开始游戏循环
scheduleUpdate(); return true;
} void HelloWorld::initPhysics()
{
//重力参数
b2Vec2 gravity;
gravity.Set(0.0f, -9.8f); //创建世界
world = new b2World(gravity); //是否允许物体休眠
world->SetAllowSleeping(true);
//开启连续的物理测试
world->SetContinuousPhysics(true);
} void HelloWorld::addNewSprite()
{
float offset = -rand() % 5;
auto visibleSize = Director::getInstance()->getVisibleSize();
auto origin = Director::getInstance()->getVisibleOrigin(); Sprite* down = Sprite::create("down.png");
down->setPosition(Vec2(visibleSize.width / 2, down->getContentSize().height));
down->setScaleY(0.5);
this->addChild(down);
b2BodyDef bodyDef;
bodyDef.position = b2Vec2(down->getPosition().x / PTM_RATIO, down->getPosition().y / PTM_RATIO);
bodyDef.type = b2_kinematicBody;
bodyDef.linearVelocity = b2Vec2(-2, 0);
b2Body* body = world->CreateBody(&bodyDef);
body->SetUserData(down);
b2PolygonShape shape1;
shape1.SetAsBox(down->getContentSize().width / 2 / PTM_RATIO, down->getContentSize().height / 2 / PTM_RATIO);
b2FixtureDef fixtureDef;
fixtureDef.shape = &shape1;
fixtureDef.density = 1.0f;
fixtureDef.friction = 1.0f;
body->CreateFixture(&fixtureDef); Sprite* up = Sprite::create("up.png");
up->setPosition(Vec2(visibleSize.width / 2, visibleSize.height - up->getContentSize().height));
up->setScaleY(0.5);
this->addChild(up); b2BodyDef upbodyDef;
upbodyDef.position=b2Vec2(up->getPosition().x / PTM_RATIO, up->getPosition().y / PTM_RATIO);
upbodyDef.type = b2_kinematicBody;
upbodyDef.linearVelocity = b2Vec2(-2, 0);
b2Body* body2 = world->CreateBody(&upbodyDef);
body2->SetUserData(up);
b2PolygonShape shape2;
shape2.SetAsBox(up->getContentSize().width / 2 / PTM_RATIO, up->getContentSize().height / 2 / PTM_RATIO);
b2FixtureDef fixtureDef2;
fixtureDef2.shape = &shape2;
body2->CreateFixture(&fixtureDef2);
} void HelloWorld::update(float dt)
{
world->Step(dt, 8, 1);
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(0);
}
}
} bool HelloWorld::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event)
{
//Touch *t = touch;
//Vec2 point = t->getLocationInView();
//point = Director::getInstance()->convertToGL(point);
//点击一次屏幕,小球上升5个像素点
//body->SetLinearVelocity(b2Vec2(-5, 5));
addNewSprite(); return false;
} void HelloWorld::createLand()
{
Size s = Director::getInstance()->getVisibleSize(); //地面物体定义
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);
}

Cocos2d-x之物理引擎的更多相关文章

  1. [原创]cocos2d-x研习录-第三阶 特性之物理引擎

    游戏物理引擎是指在游戏中涉及物理现象的逻辑处理,它用于模拟现实世界的各种物理规律(如赛车碰撞.子弹飞行.物体掉落等),让玩家能够在游戏中有真实的体验. Cocos2D-x中支持Box2D和Chipmu ...

  2. [Cocos2D-x For WP8]Box2D物理引擎

    物理引擎通过为刚性物体赋予真实的物理属性的方式来计算运动.旋转和碰撞反映.为每个游戏使用物理引擎并不是完全必要的—简单的“牛顿”物理(比如加速和减速)也可以在一定程度上通过编程或编写脚本来实现.然而, ...

  3. Cocos2d-x3.2 使用物理引擎进行碰撞检测[转]

    通常在游戏简单逻辑判断和模拟真实的物理世界时,我们只需要在定时器中判断游戏中各个精灵的条件是否满足判断条件就可以了.例如,在飞机大战中,判断我方子弹和敌机是否发生碰撞一般在定时器中通过敌机所在位置的矩 ...

  4. 实例介绍Cocos2d-x中Box2D物理引擎:碰撞检测

    在Box2D中碰撞事件通过实现b2ContactListener类函数实现,b2ContactListener是Box2D提供的抽象类,它的抽象函数:virtual void BeginContact ...

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

    我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用Box2D物理引擎的开发过程,熟悉这些API的使用.这个实例运行后的场景如图所示,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触 ...

  6. 实例介绍Cocos2d-x物理引擎:碰撞检测

    碰撞检测是使用物理引擎的一个重要目的,使用物理引擎可以进行精确的碰撞检测,而且执行的效率也很高.在Cocos2d-x 3.x中使用事件派发机制管理碰撞事件,EventListenerPhysicsCo ...

  7. 实例介绍Cocos2d-x物理引擎:HelloPhysicsWorld

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

  8. Cocos2d-x3.2总结---使用物理引擎进行碰撞检测

    [转自]: http://blog.csdn.net/cbbbc/article/details/38541099 通常在游戏简单逻辑判断和模拟真实的物理世界时,我们只需要在定时器中判断游戏中各个精灵 ...

  9. Cocos2d-x 使用物理引擎进行碰撞检测

    [转自]: http://blog.csdn.net/cbbbc/article/details/38541099 通常在游戏简单逻辑判断和模拟真实的物理世界时,我们只需要在定时器中判断游戏中各个精灵 ...

  10. 大约cocos2d-X 3.x使用引擎版本自带的物理引擎Physics

    今天打算用BOX2D物理引擎, 我想我以前听说过一些时间cocos2d-X在3.0版本封装自己的物理引擎Physics, 听名字很霸气量, 这的确是一个比BOX2D非常多( 毕竟是基于BOX2D封装的 ...

随机推荐

  1. [暑假集训Day1T1]黑暗城堡

    因为D[i]表示i号节点到1号节点的最短路径,所以可以先以1为源点跑一边SPFA,预处理出每个点到1号节点的最短路.之后开始考虑所谓的“最短路径生成树”,在这棵生成树中有以下性质:当fa[i]==no ...

  2. python学习三十五天函数递归的用法

    python函数递归就是自己调用自己,无限循环,但是python限制了调用的次数1000次,就会终止,递归用在栏目分类,采集程序比较多,下面简单说函数递归用法和实例 1,函数递归用法 def func ...

  3. JavaScript—— 案例:表单验证

    QQ号:<input type="text" id="txtQQ"><span></span><br> 邮箱:& ...

  4. 六、SQL语句进行多条件查询,并解决参数为空的情况

    一.SQL语句进行多条件查询,并解决参数为空的情况 QueryEntity query; var whereSql = new StringBuilder("Where 1=1") ...

  5. Redis和Ehcached的区别

    Redis 属于独立的运行程序,需要单独安装后,使用JAVA中的Jedis来操纵.因为它是独立,所以如果你写个单元测试程序,放一些数据在Redis中,然后又写一个程序去拿数据,那么是可以拿到这个数据的 ...

  6. 关于springmvc 整合jackson报错问题

    spring mvc 在整合jackson中报错如下 Context initialization failed org.springframework.beans.factory.BeanCreat ...

  7. 如何卸载不用的VDP

    1.首先删除VDP 2.登录AD的DNS当中,删除VDP对应的DNS解析 3.1登陆 https://vcenterip/mob 这个地址. 输入你的管理员账号密码. 3.2进入content链接. ...

  8. Sass Maps的函数-map-keys($map)

    map-keys($map) 函数将会返回 $map 中的所有 key.这些值赋予给一个变量,那他就是一个列表.如: map-keys($social-colors); 其返回的值为: "d ...

  9. Factory Methods

    The static factory method pattern is a way to encapsulate object creation. Without a factory method, ...

  10. python爬取“美团美食”汕头地区的所有店铺信息

    一.目的 获取美团美食每个店铺所有的评论信息,并保存到数据库和本地 二.实现步骤 获取所有店铺的poiId 首先观察详情页的url,后面是跟着一串数字的,而这一串数字代表着每个店铺特有的id号,我们称 ...