Cocos2d-x 3.0+ 中全新的封装的物理引擎给了开发人员最大的便捷,你不用再繁琐与各种物理引擎的细节,全然的封装让开发人员能够更快更好的将物理引擎的机制加入�到自己的游戏中,简化的设计是从2.0到3.0+的一个质的飞跃。(假设用的2.x版本号的cocos2d-x,看前一篇文章box2d)

以下相同以一个小demo来展示一下物理引擎的运用,同一时候说一下我在运用物理引擎中遇到的一些小小的问题。

Cocos2d-x 3.0+中的物理属性:

1、物理世界被集成到场景中,当你创建一个场景,你能够直接创建基于物理世界或者不使用物理世界的场景。

2、Node拥有它自己的body属性。(sprite也是node)‘

3、Cocos2d-x 3.0 已经封装了物理属性Body(PhysicsBody),Shape(PhysicsShape),Contact(PhysicsContact),Joint(PhysicsJoint)和World(PhysicsWorld),更加方便使用。

4、方便的使用listener-EventListenerPhysicsContact进行碰撞检測。

当然,封装好的物理引擎能够简化开发难度,假设有能力的话也能够直接使用Box2D和Chipmunk的原生的物理引擎进行开发,这样难度会有所提升。

以下的代码创建一个带物理世界的场景,并传递到场景中的层上。

PhysicsLayer.h中

1
2
3
4
5
6
7
8
9
10
class PhysicsLayer : public cocos2d::Layer
{
    ...
    // add following codes设置层中的物理世界
    void setPhyWorld(PhysicsWorld* world){m_world = world;}
  
    private:
        PhysicsWorld* m_world;
    ...
}

PhysicsLayer.cpp中的createScene()方法中加入�以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
Scene* PhysicsLayer::createScene()
{
    ...
    // add following codes
    auto scene = Scene::createWithPhysics();
    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);//调试
  
    auto layer = HelloWorld::create();
    layer->setPhyWorld(scene->getPhysicsWorld());//将创建的物理世界传递到子层中
    ...
    return scene;
}

Scene类有一个新的static工厂方法createWithPhysics()创建一个带物理世界的场景。能够通过getPhysicsWorld()来获取PhysicsWorld的实例。

上述代码中凝视为调试的代码在调试中很实用,它会显示游戏中物体所带有的物理边界,便于观察碰撞中的细节等。

同一时候一个场景中仅仅能有一个物理世界,全部属于这个场景的子层都共享这一个物理世界,所以在子层中用到物理世界时都会有这个定义的函数

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

进而来设置子层中的物理世界。

PhysicsWorld拥有默认的重力设置,Vector(0.0f,-98.0f),当然你也能够任意设置你想要的重力加速度,setGravity(Vect(0.0f,-200.0f)),设置重力加速度为20米每二次方秒。

创建物理边界

以下的代码创建一个物理边界

1
2
3
4
5
6
Size visibleSize = Director::getInstance()->getVisibleSize();
auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);//设置要加入�到节点中的物理body
auto edgeNode = Node::create();
edgeNode->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
edgeNode->setPhysicsBody(body);//将物理body添�到创建的节点中
scene->addChild(edgeNode);场景中加入�创建的物理节点

PhysicsWorld有非常多工厂方法,如createEdgeBox创建一个矩形的边框,參数:

1、矩形区域,设置作为VisibleSize

2、可选參数,物理材料,默觉得PHYSICSBODY_MATERIAL_DEFAULT。

3、可选參数,边框大小,默觉得1。

创建受重力影响的精灵

以下的代码创建一个受重力影响的精灵,3.0中的创建精灵代码也大大简化

1
2
3
4
5
6
7
8
9
void HelloWorld::addNewSpriteAtPosition(Point p)
{
    auto sprite = Sprite::create("circle.png");//创建精灵
    sprite->setTag(1);//设置精灵的便签值
    auto body = PhysicsBody::createCircle(sprite->getContentSize().width / 2);//创建一个附加在精灵身体上的圆形物理body
    sprite->setPhysicsBody(body);//将创建的body加到精灵身上
    sprite->setPosition(p);
    this->addChild(sprite);//加入�精灵
}

以下讲一下真正的重点所在--物理碰撞检測

谈到物理碰撞检測,真是感慨良多,在第一次运用碰撞检測时,遇到各种问题,最大的问题就是注冊完物理碰撞响应时间,写好碰撞响应函数后,竟然没反应,找各种论坛贴,各种google,最后都没有解决这个问题,最后还是在官网找到的解决方法,以下先介绍下怎样设置碰撞检測。

前面的文章讲过了3.0中的事件分发机制,所以物理引擎的碰撞事件也不例外,统一的都有事件派发器来管理。

以下代码注冊碰撞响应事件和回调函数

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

每一次碰撞检測事件是有EventListenerPhysicsContact来进行监听的。监听到碰撞事件时,会回调响应事件onContactBegin()来进行碰撞事件的处理。_eventDispatcher是事件派发器,由它管理全部的注冊事件。

EventListenerPhysicsContact是碰撞检測中的一种,也能够运用以下的来进行碰撞事件的注冊EventListenerPhysicsContactWithBodies,EventListenerPhysicsContactWithShapes,EventListenerPhysicsContactWithGroup来进行你感兴趣的bodys,shape和group事件监听。

在上面说了这么多的东西,最重要的东西就是以下的,没有以下的东西,碰撞事件根本不起作用,这就是我第一次运用碰撞时遇到的问题。也就是设置物理接触相关的位掩码值,默认的接触事件不会被接受,须要设置一定的掩码值来使接触事件响应。

接触掩码值有三个值,各自是:

1、CategoryBitmask,默认值为0xFFFFFFFF

2、ContactTestBitmask,默认值为 0x00000000

3、CollisionBitmask,默认值为0xFFFFFFFF

这三个掩码值都有相应的set/get方法来设置和获取。这三个掩码值由逻辑与来进行操作測试。

一个body的CategoryBitmask和还有一个body的ContactTestBitmask的逻辑与的结果不等于0时,接触事件将被发出,否则不发送。

一个body的CategoryBitmask和还有一个body的CollisionBitmask的逻辑与结果不等于0时,他们将碰撞,否则不碰撞

默认情况下的body属性会进行物理碰撞,但不会发送碰撞检測的信号,也就不会响应碰撞回调函数,这个能够看下默认情况下的掩码值的逻辑与

1
2
3
4
5
6
7
8
CategoryBitmask = 0xFFFFFFFF;
ContactTestBitmask = 0x00000000;
CategoryBitmask & ContactTestBitmask = 0,所以不会发送碰撞信号
 
CollisionBitmask = 0xFFFFFFFF;
 
CategoryBitmask & CollisionBitmask = 0xFFFFFFFF
所以物体会碰撞,可是不会响应碰撞回调函数。

上面介绍的掩码值是碰撞检測回调中最重要的,没有上面的掩码值,全部的碰撞回调函数都不会发生。

EventListenerPhysicsContact有四个接触回调函数:

1、onContactBegin,在接触開始时被调用,仅调用一次,通过放回true或者false来决定两个物体是否有碰撞。同一时候能够使用PhysicsContact::setData()来设置接触操作的用户数据。当返回false时,onContactPreSolve和onContactPostSolve将不会被调用,可是onContactSeperate将被调用一次。

2、onContactPreSlove ,会在每一次被调用,通过放回true或者false来决定两个物体是否有碰撞,相同能够用ignore()来跳过兴许的onContactPreSolve和onContactPostSolve回调函数。(默认返回true)

3、onContactPostSolve,在两个物体碰撞反应中的每一个步骤中被处理调用。能够在里面做一些兴许的接触操作。如销毁body

4、onContactSeperate,在两个物体分开时被调用,在每次接触时仅仅调用一次,和onContactBegin配对使用。

上述中最重要的就是碰撞检測事件的解说,这是游戏中用到碰撞常常要用到的。

好了,这篇解说了游戏中的cocos2d-x 3.x中的物理碰撞机制。以后用这个就更方便了。

cocos2d-x快乐的做让人快乐的游戏3:cocos-2d 3.x中的物理世界的更多相关文章

  1. 很多事情就像看A片,看的人觉得很爽,做的人未必。

    http://m.jingdianju.com/wzgs/shenghuo/201307185135.html 转载自: 从这个角度上来说,我不太赞成过于关注第一份工作的薪水,更没有必要攀比第一份工作 ...

  2. [转载]在澳洲做IT人士的收入差别

    澳洲跟中国一样高税收,但最大的好处是,福利返还很多:1.如果家里有孩子,每2周会有各种税收福利,就是所谓的family tax benefits (a/b):2.每财年结束还有退税:3.看病不用钱,因 ...

  3. 【科创人独家】PingCAP黄东旭:想告诉图灵这个世界现在的样子

    创业是投己所好 科创人:作为技术圈内著名艺术青年,哪个瞬间会让您更开心,完成一段优美的代码或者乐谱?还是得到来自外界的欢呼与掌声? 黄东旭:在创业之前的很长一段时间里,完成一段代码.写完一首好曲子那一 ...

  4. WP老杨解迷:如何营造让人花钱的游戏

    游戏是最好做也是最不好做的项目,游戏的好坏现在都是直接从数据来说话,Windows Phone的游戏应用同样不可能逃出这个行业准则,要说在市场里做的好,那就直接拿数据来说,几乎没人会去在乎游戏到底传达 ...

  5. 如何构建一个多人(.io) Web 游戏,第 2 部分

    原文:How to Build a Multiplayer (.io) Web Game, Part 2 探索 .io 游戏背后的后端服务器. 上篇:如何构建一个多人(.io) Web 游戏,第 1 ...

  6. Golang+Protobuf+PixieJS 开发 Web 多人在线射击游戏(原创翻译)

    简介 Superstellar 是一款开源的多人 Web 太空游戏,非常适合入门 Golang 游戏服务器开发. 规则很简单:摧毁移动的物体,不要被其他玩家和小行星杀死.你拥有两种资源 - 生命值(h ...

  7. 从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中

    //从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中 //作者:sandy //时间:2015-10-10 #inclu ...

  8. Java用户输入数值,做简单的猜数字游戏,导入基础的工具包util

    Java用户输入数值,做简单的猜数字游戏,导入基础的工具包util,导入包的方法为,import java.util.*: 完整的实例代码: /* 导入基础工具包 */ import java.uti ...

  9. 神龟快跑,2016做的一款UWP游戏

    神龟快跑,2016做的一款UWP游戏, 实际是H5页面, 用LAYA转AS3得到的 安装地址 https://www.microsoft.com/zh-cn/store/p/神龟快跑/9nblggh4 ...

随机推荐

  1. 创建webservice 用service.xml配置(复杂点的方法)

    用Axis2实现Web Service,虽然可以将POJO类放在axis2/WEB-INF/pojo目录中直接发布成Web Service,这样做不需要进行任何配置,但这些POJO类不能在任何包中.这 ...

  2. 安装Linux_[CentOS]系统

    Lunx操作系统安装 虚拟机:VirtualBox. 操作系统的选择:CentOS 6.3. (64位/32位都可). (CentOS:诞生于社区的企业级操作系统). Install Or Upgra ...

  3. JSP的学习(1)——基本知识与底层原理

    通过之前的学习,我们已经对Servlet有所了解,现在我们先来学习JSP,当能使用JSP进行友好的页面显示之后,再回去学习Servlet的其他高级特性会将整个学习很好的融入进来. JSP,即Java ...

  4. Oracle表连接总结

    1 简述 1) 两个表的连接,是通过将一个表中的一列或者多列同另一个表中的列链接而建立起来的.用来连接两张表的表达式组成了连接条件.当连接成功后,第二张表中的数据就同第一张表连接起来了,并形成了复合结 ...

  5. Android调用系统相机、自己定义相机、处理大图片

    Android调用系统相机和自己定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,而且因为涉及到要把拍到的照片显示出来,该样例也会涉及到Android载入大图片时候的处 ...

  6. LaTeX新人教程,30分钟从全然陌生到基本入门

    1.LaTeX软件的安装和使用  方法A(自助):在MikTeX的官网下载免费的MikTeX编译包并安装.下载WinEdt(收费)或TexMaker(免费)等编辑界面软件并安装.  方法B(打包):在 ...

  7. RGB HSV HLS三种色彩模式转换(C语言实现)

    Android项目上处理图像的代码(注释全部去掉) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...

  8. Codeforces Round #218 (Div. 2)

    500pt, 题目链接:http://codeforces.com/problemset/problem/371/A 分析:k-periodic说明每一段长度为k,整个数组被分成这样长度为k的片段,要 ...

  9. Tair是一个高性能,分布式,可扩展,高可靠的key/value结构存储系统(转)

    Tair是一个高性能,分布式,可扩展,高可靠的key/value结构存储系统! Tair专为小文件优化,并提供简单易用的接口(类似Map)Tair支持Java和C版本的客户端 Tair is a di ...

  10. 实时人脸检测 (Real-Time Face Detection)

    源地址:http://blog.sina.com.cn/s/blog_79b67dfe0102uzra.html 最近需要用到人脸检测,于是找了篇引用广泛的论文实现了一下:Robust Real-Ti ...