近期又弄了物理引擎。写一下吧,以下有在其它博客学习到的知识。加上自己的理解,总结下。

cocos2d-x 3.X 中全新的封装的物理引擎给了开发人员最大的便捷,你不用再繁琐与各种物理引擎的细节,全然的封装让开发人员能够更快更好的将物理引擎的机制加入到自己的游戏中,简化的设计是从2.0到3.X的一个质的飞跃。

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

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

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

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. Size visibleSize = Director::getInstance()->getVisibleSize();
  2. auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);//设要加入到节点中的物理body 
    ,这个Box是不受碰撞检測的!!!

  3. auto edgeNode = Node::create();
  4. edgeNode->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
  5. edgeNode->setPhysicsBody(body);//将物理body增加到创建的节点中
  6. scene->addChild(edgeNode);场景中加入创建的物理节点

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

1、矩形区域,设置作为VisibleSize
2、可选參数,物理材料,默觉得PHYSICSBODY_MATERIAL_DEFAULT。
3、可选參数,边框大小,默觉得1.

创建受重力影响的精灵

以下的代码创建一个受重力影响的精灵,3.0中的创建精灵代码也大大简化
  1. void HelloWorld::addNewSpriteAtPosition(Point p)
  2. {
  3. auto sprite = Sprite::create("circle.png");//创建精灵
  4. sprite->setTag(1);//设置精灵的便签值
  5. auto body = PhysicsBody::createCircle(sprite->getContentSize().width / 2);//创建一个附加在精灵身体上的圆形物理body
  6. sprite->setPhysicsBody(body);//将创建的body加到精灵身上
  7. sprite->setPosition(p);
  8. this->addChild(sprite);//加入精灵
  9. }

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

上次做《NotOneLess》项目的时候用到了物理引擎。事实上物理引擎的碰撞检測就是 对 三个掩码属性值的设置,来来回回就是设置值得问题,搞懂了这个。物理碰撞学会了80%了
看懂这个吧:点击打开链接 http://www.tuicool.com/articles/nAZbuy
以下代码注冊碰撞响应事件和回调函数
  1. auto contactListener = EventListenerPhysicsContact::create();
  2. contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);
  3. _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. CategoryBitmask = 0xFFFFFFFF;
  2. ContactTestBitmask = 0x00000000;
  3. CategoryBitmask & ContactTestBitmask = 0,所以不会发送碰撞信号
  4. CollisionBitmask = 0xFFFFFFFF;
  5. CategoryBitmask & CollisionBitmask = 0xFFFFFFFF
  6. 所以物体会碰撞,可是不会响应碰撞回调函数。
上面介绍的掩码值是碰撞检測回调中最重要的,没有上面的掩码值。全部的碰撞回调函数都不会发生。
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 物理碰撞机制的更多相关文章

  1. Cocos2D物理碰撞不按预期工作的排查工作

    如果该碰撞的节点不碰撞或反过来不该碰的碰撞了,你可以检查一下几个方面: 1.对应2个节点的分类和掩码必须匹配.如果它们应该碰撞则一个节点的分类应该在另一个节点的掩码中,反之亦然. 2.注意空的分类和掩 ...

  2. cocos2d-x 3.0游戏实例学习笔记 《跑酷》第七步--物理碰撞检測(1)

    说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...

  3. 【Unity探究】物理碰撞实验

    这几天为了准备面试,所以决定对平时学习中的盲点扫盲一下,首先想到的就是物理碰撞.以前没有好好研究过,一直模糊不清,到底什么条件下才可以产生物理碰撞呢?只要其中一个有Rigidbody就可以了吗?所以进 ...

  4. iFIERO - (二)宇宙大战 Space Battle -- SpriteKit 无限循环背景Endless、SpriteKit物理碰撞、CoreMotion加速计

    本节主要讲解如何创建无限循环Endless的星空背景(如下图).玩家飞船发射子弹,监测子弹击外星敌机的SpriteKit物理碰撞并消灭敌机,以及应用iOS的CoreMotion加速计移动飞船躲避外星敌 ...

  5. 【Unity】物理碰撞实验

    http://www.cnblogs.com/javawebsoa/archive/2013/05/18/3085818.html 这几天为了准备面试,所以决定对平时学习中的盲点扫盲一下,首先想到的就 ...

  6. Unity射击游戏实例—物理碰撞的实现

    前言: 这一篇章实现物理碰撞,就是游戏体碰撞减装甲,这几天想要试着做出兼具装甲与血量的模式,可自动回复的装甲与永久损伤的血量,在一些平台上找到了不少有意思的模型,有兴趣的可以自己找找模型替换一下. 射 ...

  7. Cocos2d-x 3.0中 物理碰撞检測中onContactBegin回调函数不响应问题

    好吧,事实上这篇也是暂时冒出来的,近期朋友要做个物理游戏,曾经做物理还是用box2d,呃.确实要花些功夫才干搞懂当中的精髓,可是听讲这套引擎又一次封装了一次.要easy非常多,所以就简单尝试了一下,感 ...

  8. U3D物理碰撞总结

    OnCollisionEnter的触发条件: 1.都有boxcollider组件并且IsTrigger为false 2.主动碰撞的物体要有非运动学刚体组件,被动碰撞的物体有木有都行 3.如果主动碰撞的 ...

  9. [UE4]碰撞机制

    应用于两种情况: 一.射线追踪,LineTrace 1.射线来自某个Trace Channel 2.Trace Channel 默认有两个:Visibility(不是可见的意思.只是Channel名称 ...

随机推荐

  1. Ubuntu16.04 下安装tomcat

    有两种常用方法: 一.通过 apt-get 命令进行在线安装(会自动配置好环境变量和服务) 二.通过下载并解压 .tar.gz 包进行手动安装(需要手动配置环境变量) 一.通过 apt-get 命令进 ...

  2. jQuery轮播图(一)轮播实现并封装

    利用面向对象自己动手写了一个封装好的jquery轮播组件,可满足一般需求,不仅使用简单且复用性高. demo:点此预览 代码地址:https://github.com/zsqosos/componen ...

  3. LeetCode 533----Lonely Pixel II

    问题描述 Given a picture consisting of black and white pixels, and a positive integer N, find the number ...

  4. Python - Exceptions

    官方文档:https://docs.python.org/3/library/exceptions.html 1. 使用try...except... 2. 输出错误信息的方式为: try: curs ...

  5. Android 黑色样式menu

    效果图:

  6. Linked List Cycle 判断一个链表是否存在回路(循环)

    Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ext ...

  7. Unity射线

    //射线原点 [SerializField] Transform tr; //射线长度    [SerializField] float dis = 5; //射线停留时间 [SerializFiel ...

  8. 毕向东_Java基础视频教程第21天_IO流(1)

    第21天-01-IO流(对象的序列化) ObjectInputStream与ObjectOutputStream 被操作的对象需要实现Serializable接口(标记接口) 非必须, 但强烈建议所有 ...

  9. CentOS7中永久保存systemd日志

    将systemd的日志写入磁盘: 1.在/var/log/目录下创建日志存放目录,并加入systemd-journal的权限: ~]#mkdir /var/log/journal ~]#chown r ...

  10. pt-summary

    pt-summary主要是用来统计机器信息: [root@mxqmongodb2 bin]# ./pt-summary # Percona Toolkit System Summary Report ...