文档章节

cocos2d-x 3.2 物理碰撞机制

piggybear
 piggybear
发布于 2015/02/16 10:31
字数 1891
阅读 19
收藏 0
点赞 0
评论 0

cocos2d-x 3.0+ 中全新的封装的物理引擎给了开发者最大的便捷,你不用再繁琐与各种物理引擎的细节,完全的封装让开发者可以更快更好的将物理引擎的机制添加到自己的游戏中,简化的设计是从2.0到3.0+的一个质的飞跃。

下面同样以一个小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中

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. class PhysicsLayer : public cocos2d::Layer  
  2. {  
  3.     ...  
  4.     // add following codes设置层中的物理世界  
  5.     void setPhyWorld(PhysicsWorld* world){m_world = world;}  
  6.    
  7.     private:  
  8.         PhysicsWorld* m_world;  
  9.     ...  
  10. }  
PhysicsLayer.cpp中的createScene()方法中添加下面代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Scene* PhysicsLayer::createScene()  
  2. {  
  3.     ...  
  4.     // add following codes  
  5.     auto scene = Scene::createWithPhysics();  
  6.     scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);//调试  
  7.    
  8.     auto layer = HelloWorld::create();  
  9.     layer->setPhyWorld(scene->getPhysicsWorld());//将创建的物理世界传递到子层中  
  10.     ...  
  11.     return scene;  
  12. }  

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

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 在CODE上查看代码片 派生到我的代码片
  1. Size visibleSize = Director::getInstance()->getVisibleSize();  
  2. auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);//设置要添加到节点中的物理body  
  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 在CODE上查看代码片 派生到我的代码片
  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. }  

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

谈到物理碰撞检测,真是感慨良多,在第一次运用碰撞检测时,遇到各种问题,最大的问题就是注册完物理碰撞响应时间,写好碰撞响应函数后,居然没反应,找各种论坛贴,各种google,最后都没有解决问题,最后还是在官网找到的解决方法,下面先介绍下如何设置碰撞检测。
前面的博客讲过了3.0中的事件分发机制,所以物理引擎的碰撞事件也不例外,统一的都有事件派发器来管理。
下面代码注册碰撞响应事件和回调函数
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 在CODE上查看代码片 派生到我的代码片
  1. CategoryBitmask = 0xFFFFFFFF;  
  2. ContactTestBitmask = 0x00000000;  
  3. CategoryBitmask & ContactTestBitmask = 0,所以不会发送碰撞信号  
  4.   
  5. CollisionBitmask = 0xFFFFFFFF;  
  6.   
  7. CategoryBitmask & CollisionBitmask = 0xFFFFFFFF  
  8. 所以物体会碰撞,但是不会响应碰撞回调函数。  
上面介绍的掩码值是碰撞检测回调中最重要的,没有上面的掩码值,所有的碰撞回调函数都不会发生。
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配对使用。
上述中最重要的就是碰撞检测事件的讲解,这是游戏中用到碰撞经常要用到的。
好了,这篇讲解了游戏中的物理碰撞机制。

转自:http://blog.csdn.net/hust_superman/article/details/38355985

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

共有 人打赏支持
piggybear
粉丝 3
博文 237
码字总数 37552
作品 0
西安
技术主管
实例介绍Cocos2d-x物理引擎:碰撞检测

碰撞检测是使用物理引擎的一个重要目的,使用物理引擎可以进行精确的碰撞检测,而且执行的效率也很高。 在Cocos2d-x 3.x中使用事件派发机制管理碰撞事件,EventListenerPhysicsContact是碰撞...

智捷课堂 ⋅ 2014/09/26 ⋅ 1

《Cocos2d-x实战 工具卷》上线了

感谢大家一直以来的支持! 各大商店均开始销售: 京东:http://item.jd.com/11659696.html 当当:http://product.dangdang.com/23659809.html 《Cocos2d-x实战 工具卷》素材及样章下载地址:...

智捷课堂 ⋅ 2015/03/26 ⋅ 0

《Cocos2d-x实战 C++卷》上线了-源码-样章-感谢大家的支持

《Cocos2d-x实战 C++卷》上线了 感谢大家一直以来的支持! 全面介绍Cocos开发技巧,采用Cocos2d-x3.2版本,并且详细介绍跨平台移植已经多平台发布细节。 · 各大商店均开始销售: 京东:htt...

智捷课堂 ⋅ 2014/12/01 ⋅ 0

quick-cocos2d-x物理引擎之chipmunk(一)

chipmunk是一个用C写成的物理引擎,quick-cocos2d-x已经用C++对其进行封装,导出到lua的类有: CCPhysicsWorldCCPhysicsBodyCCPhysicsShapeCCPhysicsDebugNodeCCPhysicsCollisionEventCCPhys......

lonewolf ⋅ 2013/11/01 ⋅ 0

实例介绍Cocos2d-x物理引擎:HelloPhysicsWorld

我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用物理引擎的开发过程,熟悉这些API的使用。这个实例的运行后的场景,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一...

智捷课堂 ⋅ 2014/09/22 ⋅ 0

使用SpriteBuilder制作Cocos2D游戏完全中文教程(六)

使用Chipmunk添加物理效果,第1部分(Add Physics using Chipmunk, Part 1) 现在我们需要构建一个真实的发射机制,这之前我们需要了解一些基础知识。 为什么锚点对发射臂来说很重要? 你还记...

wealpan ⋅ 2014/03/03 ⋅ 11

实例介绍Cocos2d-x中Box2D物理引擎:碰撞检测

在Box2D中碰撞事件通过实现b2ContactListener类函数实现,b2ContactListener是Box2D提供的抽象类,它的抽象函数: virtual void BeginContact(b2Contact contact)。两个物体开始接触时会响应...

智捷课堂 ⋅ 2014/10/09 ⋅ 0

quick-cocos2d-x物理引擎之chipmunk(二)

上一篇讲了quick-cocos2d-x使用chipmunk的使用流程,介绍了World,Body,Shape的建立,这一篇将讲解如何处理物体之间的碰撞。 一、监听事件 quick-cocos2d-x中的chipmunk碰撞处理是通过监听事件...

lonewolf ⋅ 2013/11/02 ⋅ 0

购买李宁Cocos2d-x套餐,送最新出的《Cocos2d-x游戏实战指南》签名书一本

活动时间:2016-10-18至2016-11-30 通过本套餐,可完全了解Cocos2d-x 3.x的相关技术,以及掌握C++语言,并具有一定的项目实战经验。 Cocos2d-x游戏开发套餐:http://edu.51cto.com/pack/vie...

androidguy ⋅ 2016/10/17 ⋅ 0

【Unity3D基础概念】给初学者看的Unity概览(一):GameObject,Compoent,Time,Input,Physics

点击进入我的新博客 作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明。如果你喜欢这篇文章,请点推荐。谢谢! Unity3D重要模块的类图 最近刚刚完成了一个...

王选易 ⋅ 2014/05/29 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Springboot2 之 Spring Data Redis 实现消息队列——发布/订阅模式

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式,这里利用redis消息“发布/订阅”来简单实现订阅者模式。 实现之前先过过 redis 发布订阅的一些基础概念和操...

Simonton ⋅ 29分钟前 ⋅ 0

error:Could not find gradle

一.更新Android Studio后打开Project,报如下错误: Error: Could not find com.android.tools.build:gradle:2.2.1. Searched in the following locations: file:/D:/software/android/andro......

Yao--靠自己 ⋅ 昨天 ⋅ 0

Spring boot 项目打包及引入本地jar包

Spring Boot 项目打包以及引入本地Jar包 [TOC] 上篇文章提到 Maven 项目添加本地jar包的三种方式 ,本篇文章记录下在实际项目中的应用。 spring boot 打包方式 我们知道,传统应用可以将程序...

Os_yxguang ⋅ 昨天 ⋅ 0

常见数据结构(二)-树(二叉树,红黑树,B树)

本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自coursera上普林斯顿的课程《Algorithms, Part I》中的Slides 相关命题的证明可参考《算法(第...

浮躁的码农 ⋅ 昨天 ⋅ 0

android -------- 混淆打包报错 (warning - InnerClass ...)

最近做Android混淆打包遇到一些问题,Android Sdutio 3.1 版本打包的 错误如下: Android studio warning - InnerClass annotations are missing corresponding EnclosingMember annotation......

切切歆语 ⋅ 昨天 ⋅ 0

eclipse酷炫大法之设置主题、皮肤

eclipse酷炫大法 目前两款不错的eclipse 1.系统设置 Window->Preferences->General->Appearance 2.Eclipse Marketplace下载【推荐】 Help->Eclipse Marketplace->搜索‘theme’进行安装 比如......

anlve ⋅ 昨天 ⋅ 0

vim编辑模式、vim命令模式、vim实践

vim编辑模式 编辑模式用来输入或修改文本内容,编辑模式除了Esc外其他键几乎都是输入 如何进入编辑模式 一般模式输入以下按键,均可进入编辑模式,左下角提示 insert(中文为插入) 字样 i ...

蛋黄Yolks ⋅ 昨天 ⋅ 0

大数据入门基础:SSH介绍

什么是ssh 简单说,SSH是一种网络协议,用于计算机之间的加密登录。 如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码...

董黎明 ⋅ 昨天 ⋅ 0

web3j教程

web3j是一个轻量级、高度模块化、响应式、类型安全的Java和Android类库提供丰富API,用于处理以太坊智能合约及与以太坊网络上的客户端(节点)进行集成。 汇智网最新发布的web3j教程,详细讲解...

汇智网教程 ⋅ 昨天 ⋅ 0

谷歌:安全问题机制并不如你想象中安全

腾讯科技讯 5月25日,如今的你或许已经对许多网站所使用的“安全问题机制”习以为常了,但你真的认为包括“你第一个宠物的名字是什么?”这些问题能够保障你的帐户安全吗? 根据谷歌(微博)安...

问题终结者 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部