文档章节

cocos2dx 3.0 物理引擎概述

piggybear
 piggybear
发布于 2015/02/16 10:27
字数 2125
阅读 29
收藏 0

概述

在游戏中模拟真实的物理世界是个比较麻烦的,通常都是交给物理引擎来做。比较知名的有Box2D了,它几乎能模拟所有的物理效果,而chipmunk则是个更轻量的引擎等。在Cocos2d-x 2.0中,游戏直接使用物理引擎,引擎提供了一个简单的CCPhysicsSprite,处理了物理引擎的body与CCSprite的关系,而物理引擎的其他要素并没有和引擎对应起来,游戏需要选择直接调用chipmunk或Box2D的api来处理逻辑。然而直接使用物理引擎是比较复杂的,它物理引擎的接口参赛很多,很复杂,而且需要开发人员对物理引擎和Cocos2d-x都很了解,才能把两者融合得很好。

这个情况在3.0中有了改变,全新的Physics integration,把chipmunk和Box2D封装到引擎内部,游戏开发不用关心底层具体是用的哪个物理引擎,不用直接调用物理引擎的接口。

物理引擎和Cocos2d-x进行了深度融合:

  • 物理世界被融入到Scene中,即当创建一个场景时,就可以指定这个场景是否使用物理引擎。
  • Node自带body属性,也就是sprite自带body属性。
  • Cocos2d-x 3.0对物理引擎的Body(PhysicsBody),Shape(PhysicsShape),Contact(PhysicsContact),Joint(PhysicsJoint),World(PhysicsWorld)进行了封装抽象,使用更简单。
  • 更简单的碰撞检测监听EventListenerPhysicsContact。

创建带物理引擎的游戏工程

在3.0中创建工程由/tools/project-creator下的create_project.py脚本完成。

默认创建的工程已支持物理引擎,内部启用的是chipmunk。

你可以注释掉ccConfig.h里的CC_USE_PHYSICS宏定义去关闭它。

创建带物理世界的scene

下面的代码创建带物理世界的scene,并传递给child layer。

在.h文件中添加以下代码

void setPhyWorld(PhysicsWorld* world){m_world = world;}
private:
    PhysicsWorld* m_world;

在.cpp文件的createScene方法中添加以下代码

auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

auto layer = HelloWorld::create();
layer->setPhyWorld(scene->getPhysicsWorld());

Scene类有了新的静态工厂方法,createWithPhysics(),创建带物理世界的scene。
Scene的getPhysicsWorld()方法获取PhysicsWorld实例,

PhysicsWorld的setDebugDrawMask()方法,在调试物理引擎中是很有用的,它把物理世界中不可见的shape,joint,contact可视化。当调试结束,游戏发布的时候,你需要把这个debug开关关闭。

通过setPhyWorld()方法来传递PhysicsWorld给ChildLayer。一个scene只有一个PhysicsWorld,其下的所有layer共用一个PhysicsWorld实例。

PhysicsWorld默认是有带重力的,默认大小为Vect(0.0f, -98.0f), 你也可以通过的setGravity()方法来设置Physics的重力参数。

你还可以通过setSpeed()来设置物理世界的模拟速度。

创建物理边界

我们知道物理世界中,所有物体受重力的影响。
物理引擎提供staticShape创建一个不受重力影响的形状,在Cocos2d-x 2.0中,我们需要了解物理引擎的staticShape相关的各种参数来完成边界设置。

在3.0中,PhysicsShape属于Node的一个属性,要设置PhysicsWorld的属性,都需要通过一个Node实例来中介传达。

下面的代码展示如何创建一个围绕屏幕四周的物理边界。

Size visibleSize = Director::getInstance()->getVisibleSize();
auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);
auto edgeNode = Node::create();
edgeNode->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
edgeNode->setPhysicsBody(body);
scene->addChild(edgeNode);

PhysicsBody包含很多工厂方法,createEdgeBox创建一个矩形边界,参数含义依次是:

  1. 矩形区域大小,这里设置为visibleSize。
  2. 设置材质,可选参数,默认为PHYSICSBODY_MATERIAL_DEFAULT。
  3. 边线宽度,可选参数,默认为1。

然后我们创建一个Node,把刚才创建的body附加到Node上,并设置好Node的position为屏幕中心点。
最后,把Node添加到scene。

Node的addChild方法,在3.0中,有对物理body做处理,它会自动把node的body设置到scene的PhysicsWorld上去。

PhysicsBody中的工程方法,针对参数设置的body大小,会自动创建对应的PhysicsBody和一个PhysicsShape,这也是通常情况下,直接使用物理引擎创建一个body需要做的事情。3.0的Physics integration极大的简化了使用物理引擎的代码量。

创建受重力作用的sprite

在3.0中创建一个受重力作用的Sprite也很简单。

void HelloWorld::addNewSpriteAtPosition(Point p)
{
    auto sprite = Sprite::create("circle.png");
    sprite->setTag(1);
    auto body = PhysicsBody::createCircle(sprite->getContentSize().width / 2);
    sprite->setPhysicsBody(body);
    sprite->setPosition(p);
    this->addChild(sprite);
}

首先创建一个sprite,然后用PhysicsBody::createCircle创建一个圆形的body附加在sprite上。
整个过程和之前创建边界的过程是一致的。

你也可以创建自己的PhysicsShape然后通过PhysicsBody的addShape()方法加入到body中,但需要注意的是,shape的重量(mess,通过密度和体积计算得出)和转动惯量(moment)是会自动加到body上的,并且shape加到body后是不能改变它相对于body的位置和角度的,不需要时可以通过removeShape()来移除。

碰撞检测

Cocos2d-x中,事件派发机制做了重构,所有事件均有事件派发器统一管理。物理引擎的碰撞事件也不例外,
下面的代码注册碰撞begin回调函数。

auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

碰撞检测的所有事件由EventListenerPhysicsContact来监听,创建一个实例,然后设置它的onContactBegin回调函数,CC_CALLBACK_1是Cocos2d-x 3.0使用C++ 11的回调函数指针转换助手函数,由于onContactBegin回调有一个参数,所有这里使用CC_CALLBACK_1来做转换。

_eventDispatcher是基类Node的成员,Layer初始化后就可直接使用。

你还可以使用EventListenerPhysicsContactWithBodiesEventListenerPhysicsContactWithShapesEventListenerPhysicsContactWithGroup 来监听你感兴趣的两个物体、两个形状,或者某组物体的碰撞事件,但是要注意设置物体碰撞相关的mask值(下面会详细说明),因为物体碰撞事件在默认情况下是不接收的,即使你创建了相应的EventListener。

PhysicsBody碰撞相关的mask设置和group设置跟Box2D的设置是一致的。

mask设置分为**CategoryBitmask**, ContactTestBitmask 和 CollisionBitmask,你可以通过相关的get/set接口来获得或者设置他们。

他们是通过逻辑与来进行测试的。

当一个物体的**CategoryBitmask**跟另一个物体的**ContactTestBitmask**的逻辑与结果不为零时,将会发送相应的事件,否则不发送。

而当一个物体的**CategoryBitmask**跟另一个物体的**CollisionBitmask**的逻辑与测试结果不为零时,将会发生碰撞,否则不发生碰撞。

注意,在默认情况下**CategoryBitmask**的值为0xFFFFFFFF,**ContactTestBitmask**的值为0x00000000,**CollisionBitmask**的值为0xFFFFFFFF,也就是说默认情况下所有物体都会发生碰撞但不发送通知。


另一个碰撞相关的设置是**group**(组),当它大于零时,同组的物体将发生碰撞,当它小于零时,同组的物体不碰撞。注意,当**group**不为零时,他将忽略mask的碰撞设置(是否通知的设置依然有效)。

EventListenerPhysicsContact里有四个碰撞回调函数,他们分别是onContactBeginonContactPreSolveonContactPostSolveonContactSeperate

在碰撞刚发生时,onContactBegin会被调用,并且在此次碰撞中只会被调用一次。你可以通过返回true或者false来决定物体是否发生碰撞。你可以通过PhysicsContact::setData()来保存自己的数据以便用于后续的碰撞处理。需要注意的是,onContactBegin返回flase时,onContactPreSolveonContactPostSolve将不会被调用,但onContactSeperate必定会被调用。

onContactPreSolve发生在碰撞的每个step,你可以通过调用PhysicsContactPreSolve的设置函数来改变碰撞处理的一些参数设定,比如弹力,阻力等。同样你可以通过返回true或者false来决定物体是否发生碰撞。你还可以通过调用PhysicsContactPreSolve::ignore()来跳过后续的onContactPreSolveonContactPostSolve回调事件通知(默认返回true)。

onContactPostSolve发生在碰撞计算完毕的每个step,你可以在此做一些碰撞的后续处理,比如摧毁某个物体等。

onContactSeperate发生在碰撞结束两物体分离时,同样只会被调用一次。它跟onContactBegin必定是成对出现的,所以你可以在此摧毁你之前通过PhysicsContact::setData()设置的用户数据。


转自:http://blog.csdn.net/hanbingfengying/article/details/37519287

本文转载自:http://blog.csdn.net/aa294194253/article/details/38688413

共有 人打赏支持
piggybear
粉丝 3
博文 237
码字总数 37552
作品 0
西安
技术主管
私信 提问
cocos2d-x js模版修改

创建cocos2d-x项目,导入引擎模版,避免每次都拷贝引擎到项目中,修改路径: D:commonscocos2d-xcocos2d-2.1rc0-x-2.1.3templatemsvcCCAppWiz.win32Scripts1033下的js文件如下: // Additio...

石头哥哥
2013/08/04
0
0
cocos2dx 3.0正式版 在mac上新建项目

今天就分享mac 上 cocos2dx 3.0 正式版 创建一个新项目 下载cocos2dx 3.0正式版 下载好后打开终端,cd 进入 cocos2d-x-3.0/tools/cocos2d-console/bin 把cocos.py 拖到终端,然后确定 确定后...

千山万水
2014/06/02
0
0
cocos2dx学习日志(一) 总之先弄个能跑的apk出来吧!

新年新气象,新的一年已经开始好一阵子了。本着人在江湖,技多不压身的原则,最近的开始利用业余时间学习cocos2dx游戏引擎开发,话说自己写个游戏那是我儿时的梦想,哈。 废话不多说直接进正...

soso_fy
2014/02/26
0
0
cocos2dx游戏开发实战之贪吃蛇视频教程

课程目标:让学员能够从零开始学会使用cocos2dx游戏引擎,且通过贪吃蛇的实战,让学员能够快速使用cocos2dx游戏引擎开发游戏。 适合人群:初学者,有C++基础。 cocos2dx是当前比较火的一款2...

星辰8209
07/26
0
0
杨超 (wantnon)/EffectNodes-for-Cocos2dx

EffectNodes for Cocos2dx by yang chao (wantnon), 2014-6-26 EffectNodes for Cocos2dx is a collection of 2d special effects implemented with cocos2dx. i will add more when i got g......

杨超 (wantnon)
05/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

day176-2018-12-13-英语流利阅读-待学习

人造的肉你敢吃吗? Lala 2018-12-13 1.今日导读 在过去的几十年里,肉类替代品已经从简单的大豆制品进化成了更像肉类的东西,比如以植物为原料的汉堡。然而,最近有公司已经生产出了完全用动...

飞鱼说编程
9分钟前
0
0
mysql 按小时统计

表里记录了有时间戳和对应的当年登录的玩家数量,现在希望看到一个月内每个小时,登录玩家的平均数量。 之前是写的一个脚本,写了一个循环,每次获取一个小时的平均数,放在数组里,再导出文...

bobway
14分钟前
1
0
TiQuery:All Diagnosis in SQL | TiDB Hackathon 优秀项目分享

本文作者是来自 TiNiuB 队的黄梦龙同学,他们的项目 TiQuery 在本届 TiDB Hackathon 2018 中获得了三等奖。 TiQuery 可以搜集诊断集群问题所需要的信息,包括集群拓扑,Region 分布,配置,各...

TiDB
25分钟前
2
0
git 分支创建合并流程图

gentlelions
34分钟前
3
0
Kali Linux常用服务配置教程DHCP服务原理

Kali Linux常用服务配置教程DHCP服务原理 动态主机配置协议(Dynamic Host Configuration Protocol,简称DHCP)是一个局域网的网络协议,基于UDP协议工作。它主要有两个用途:第一,给内部网...

大学霸
34分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部