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

  在很多的游戏设计中一般都会涉及和模拟到真实的物理世界。然而游戏中模拟真实世界的物理会很复杂。使用已经写好的物理引擎会用很大的帮助和便利。 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. 标签的增加、删除与复制,动态标签js不生效的解决

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 我心中的ASP.NET Core 新核心对象WebHost(二)

    这是ASP.NET Core新核心对象系列的第二篇,上一篇 WebHost准备阶段 我们讲到了WebHostBuilder的初始化及配置.我们给WebHostBuilder进行以下配置 UseKest ...

  3. 【学习总结】GirlsInAI ML-diary day-21-初识 Numpy, Matplotlib, Seanborn [柱状图、折线图、箱图]

    [学习总结]GirlsInAI ML-diary 总 原博github链接-day21 初识 Numpy, Matplotlib, Seanborn [柱状图.折线图.箱图] 一.Titanic练习赛 ...

  4. js的label标签语句与with语句的用法

    /** * label标签语句 * - 语法: * 标签名: 语句 * 如:start: n = 1; * 上面标签start可以被之后的break或continue语句引用 * - label标签语 ...

  5. linux单机部署kafka(filebeat+elk组合)

    filebeat+elk组合之kafka单机部署 准备: kafka下载链接地址:http://kafka.apache.org/downloads.html 在这里下载kafka_2.12-2.10 ...

  6. 十、.NET使用本地Outlook邮箱指定邮箱用户名和密码发送邮件

    十..NET使用本地Outlook邮箱指定邮箱用户名和密码发送邮件 1.添加Microsoft.Office.Interop.Outlook引用 2.封装发送邮件方法 using System; us ...

  7. Linux 脚本运维总结之Shell script

    1. 本地变量和环境变量 变量类型 定义形式 声明位置 显示命令 作用域 本地变量 VARNAME=value 命令行或shell脚本 set (显示所有变量) 本用户,本进程 环境变量 export ...

  8. MySQL中常见函数

    一.日期函数 1.NOW()   返回当前日期和时间 mysql> SELECT NOW(); +---------------------+ | NOW() | +-------------- ...

  9. 10.VScode Debug——2019年12月12日

    title: vscode debug date: "2019-09-17 16:17:16" tags: 技巧 categories: 技术驿站 1.为什么需要调试 写了很多行代 ...

  10. ExtJS5.0 菜鸟的第一天

    1.新项目开始啦,后台用户管理页面涉及到表格数据添加,修改内容比较多.准备用EXTJS框架搞下,对于我这种JS不咋地的人来说,还真是个挑战.整了2天,才搞出一个Hello,world!我也是醉了.. ...