cocos2d-x 3.x 物理碰撞机制

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

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中

[cpp] view
plain
copy

  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()方法中添加下面代码:

[cpp] view
plain
copy

  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的实例。

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

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

[cpp] view
plain
copy

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

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

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

创建物理边界

下面的代码创建一个物理边界,其实就是做外面的边界框

[cpp] view
plain
copy

  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中的创建精灵代码也大大简化

[cpp] view
plain
copy

  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

下面代码注册碰撞响应事件和回调函数

[cpp] view
plain
copy

  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属性会进行物理碰撞,但不会发送碰撞检测的信号,也就不会响应碰撞回调函数,这个可以看下默认情况下的掩码值的逻辑与

[cpp] view
plain
copy

  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配对使用。

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

好了,这篇讲解了游戏中的物理碰撞机制。

时间: 2024-10-26 19:19:04

cocos2d-x 3.x 物理碰撞机制的相关文章

cocos2d-x 3.2 物理碰撞机制

cocos2d-x 3.0+ 中全新的封装的物理引擎给了开发者最大的便捷,你不用再繁琐与各种物理引擎的细节,完全的封装让开发者可以更快更好的将物理引擎的机制添加到自己的游戏中,简化的设计是从2.0到3.0+的一个质的飞跃. 下面同样以一个小demo来展示一下物理引擎的运用,同时说一下我在运用物理引擎中遇到的一些小小的问题. cocos2d-x 3.0+中的物理属性: 1.物理世界被集成到场景中,当你创建一个场景,你可以直接创建基于物理世界或者不使用物理世界的场景. 2.Node拥有它自己的bod

unity3d研究1-物理碰撞OnCollision和非物理碰撞OnTrigge的区别

物理碰撞OnCollision,发生真实的碰撞效果(互撞被推开),实际是一个碰撞器 条件:两个物体都必须带有碰撞器(Collider),最少一个物体带有Rigidbody刚体. 1.MonoBehaviour.OnCollisionEnter(Collision collision) 当进入碰撞器 2.MonoBehaviour.OnCollisionExit(Collision collision) 当退出碰撞器 3.MonoBehaviour.OnCollisionStay(Collisio

Cocos2d之“引用计数”内存管理机制实现解析

一.引言 本文主要分析cocos2d游戏开发引擎的引用计数内存管理技术的实现原理.建议读者在阅读本文之前阅读笔者之前一篇介绍如何使用cocos2d内存管理技术的文章--<Cocos2d之Ref类与内存管理使用详解>. 二.相关概念 引用计数 引用计数是计算机编程语言的一种内存管理技术,是指将资源(对象.内存或者磁盘空间等)的被引用计数保存起来,当引用计数变为零时就将资源释放的过程.使用引用计数技术可以实现自动内存管理的目的. 当实例化一个类时,对象的引用计数为1,在其他对象需要持有这个对象时,

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

好吧,事实上这篇也是暂时冒出来的,近期朋友要做个物理游戏,曾经做物理还是用box2d,呃.确实要花些功夫才干搞懂当中的精髓,可是听讲这套引擎又一次封装了一次.要easy非常多,所以就简单尝试了一下,感觉确实要简单不少,只是在这当中还是遇到了些问题,首先就来说说onContactBegin这个回调函数响应问题. 先说说情况.简单做了一个打砖块的游戏.前面一切都非常顺利,仅仅是做到碰撞检測的时候,发现回调函数弄死都不调用.開始我以为函数写错了,后来查了api.testCpp都没有错,在3.0的api

[UE4]碰撞机制

应用于两种情况: 一.射线追踪,LineTrace 1.射线来自某个Trace Channel 2.Trace Channel 默认有两个:Visibility(不是可见的意思.只是Channel名称)/Camera(不是相机的意思.只是Channel名称),可增加自定义的Channel Mesh也可以设置碰撞预设. 3.组件可以自定定义对Trace Channel的响应方式 在蓝图运行时也可以设置碰撞预设,运行时设置的碰撞预设会覆盖掉在设计时的碰撞预设. 二.物体之间的碰撞 1.默认有好几种,

物理碰撞--js

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>test.html</title> 5 <meta charset="UTF-8"> 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="

cocos2d-x快乐的做让人快乐的游戏3:cocos-2d 3.x中的物理世界

Cocos2d-x 3.0+ 中全新的封装的物理引擎给了开发人员最大的便捷,你不用再繁琐与各种物理引擎的细节,全然的封装让开发人员能够更快更好的将物理引擎的机制加入?到自己的游戏中,简化的设计是从2.0到3.0+的一个质的飞跃.(假设用的2.x版本号的cocos2d-x,看前一篇文章box2d) 以下相同以一个小demo来展示一下物理引擎的运用,同一时候说一下我在运用物理引擎中遇到的一些小小的问题. Cocos2d-x 3.0+中的物理属性: 1.物理世界被集成到场景中,当你创建一个场景,你能够

cocos2d-x 事件分发机制 ——加速计事件监听

加速计事件监听机制 在上一篇中介绍了cocos2d-x中的触摸事件机制,这篇来介绍下游戏中也经常用到的加速计事件,这些都是游戏中的经常要用到的. 移动设备上一个很重要的输入源是设备的方向,大多数设备都配备了加速计,用于测量设备静止或匀速运动时所受到的重力方向. 重力感应来自移动设备的加速计,通常支持X.Y和Z三个方向的加速度感应,又称为三向加速计.实际应用中,可以根据三个方向的力度大小来计算手机倾斜的角度和方向. 3.0机制中,我们只需要创建一个加速计监听器EventListenerAccele

cocos2dx-3.x物理引擎Box2D介绍

物理引擎 Cocos2d-x引擎内置了两种物理引擎,它们分别是Box2D和Chipmunk,都是非常优秀的2D物理引擎,而且x引擎将它们都内置在SDK中.Box2D使用较为广泛,在这里选择Box2D来进行学习.  物理引擎模拟的内容: 重力:在游戏中模拟重力加速度,当游戏中人物跳跃起来后会受到重力影响而向下移动,在没有地面的场景,人物和物体会由于重力而做自由落体运动.牵引力(动力):在游戏中比如汽车的引擎,人物本身能够提供向前进行的动力,这种牵引力是持续不断地作用在物体上的,物体因此可以向作用力