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

virtual void EndContact(b2Contact* contact)。分离时响应。

但仅仅调用一次。

virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)。持续接触时响应,它会被多次调用。

virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)。持续接触时响应,调用完preSolve后调用。

以下通过将12.2.3一节的实例採用Box2D技术重构。了解一下Box2d物理引擎中怎样检測碰撞。
首先我们须要在project中加入一个新类。

使用Visual Studio 2012中加入一个新类。须要分别加入C++源文件和头文件。详细操作,如图所看到的。右键点击projectHelloBox2D下的Classes目录。在右键菜单中选择。“加入”→ “新项目”。

弹出如后面的图所看到的加入新项对话框,我们在对话框中选择文件的种类,在“名称”中输入文件名称ContactListener,然后点击“加入”button加入文件。

Visual Studio 2012中加入新类

加入新项对话框

加入完毕新类ContactListener。我们还须要改动它的代码,ContactListener.h文件代码例如以下:

  1. #include "cocos2d.h"
  2. #include "Box2D/Box2D.h"
  3.  
  4. USING_NS_CC;
  5.  
  6. class ContactListener : public b2ContactListener
  7. {
  8. private:
  9. //两个物体開始接触时会响应
  10. virtual void BeginContact(b2Contact* contact);
  11.  
  12. //持续接触时响应
  13. virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
  14. //持续接触时响应,调用完preSolve后调用
  15. virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
  16.  
  17. //分离时响应
  18. virtual void EndContact(b2Contact* contact);
  19. };
  20. 在头文件里须要引入cocos2d.hBox2D/Box2D.h头文件,否则会有编译错误。ContactListener採用共同拥有继承b2ContactListener
  21. ContactListener.cpp文件代码例如以下:
  22. #include "ContactListener.h"
  23.  
  24. void ContactListener::BeginContact(b2Contact* contact)
  25. {
  26. log("BeginContact");
  27.  
  28. b2Body* bodyA = contact->GetFixtureA()->GetBody();
  29. b2Body* bodyB = contact->GetFixtureB()->GetBody();
  30. auto spriteA = (Sprite*)bodyA->GetUserData();
  31. auto spriteB = (Sprite*)bodyB->GetUserData();
  32.  
  33. if (spriteA != nullptr && spriteB != nullptr)
  34. {
  35. spriteA->setColor(Color3B::YELLOW);
  36. spriteB->setColor(Color3B::YELLOW);
  37. }
  38. }
  39.  
  40. void ContactListener::EndContact(b2Contact* contact)
  41. {
  42. log("EndContact");
  43.  
  44. b2Body* bodyA = contact->GetFixtureA()->GetBody();
  45. b2Body* bodyB = contact->GetFixtureB()->GetBody();
  46. auto spriteA = (Sprite*)bodyA->GetUserData();
  47. auto spriteB = (Sprite*)bodyB->GetUserData();
  48.  
  49. if (spriteA != nullptr && spriteB != nullptr)
  50. {
  51. spriteA->setColor(Color3B::WHITE);
  52. spriteB->setColor(Color3B::WHITE);
  53. }
  54. }
  55.  
  56. void ContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
  57. {
  58. log("PreSolve");
  59. }
  60.  
  61. void ContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
  62. {
  63. log("PostSolve");
  64. }

上述代码第①行是实现碰撞事件BeginContact函数,第②代码和第③行代码是获得接触两方物体对象。第④代码和第⑤行代码是从物体对象的UserData属性中确定精灵对象,UserData属性可以放置不论什么对象,这里我们可以通过bodyA->GetUserData()语句取得精灵,那是由于在定义物体的时候通过body->SetUserData(sprite)语句,将精灵放入到物体的UserData属性。

第⑥行代码是推断两个精灵是否存在。

代码第⑦行是实现碰撞事件EndContact函数。函数的实现与BeginContact函数相似。第⑧和第⑨行代码是实现碰撞事件PreSolve和PostSolve函数。这两个函数通经常使用的不多。

我们还须要在要监听事件的层中,加入相关碰撞检測代码。在HelloWorld.h的代码例如以下:

  1. #ifndef __HELLOWORLD_SCENE_H__
  2. #define __HELLOWORLD_SCENE_H__
  3.  
  4. #include "cocos2d.h"
  5. #include "Box2D/Box2D.h"
  6. #include "ContactListener.h"
  7.  
  8. #define PTM_RATIO 32
  9.  
  10. class HelloWorld : public cocos2d::Layer
  11. {
  12. b2World* world;
  13. ContactListener* contactListener;
  14.  
  15. public:
  16.  
  17. ~HelloWorld();
  18.  
  19. static cocos2d::Scene* createScene();
  20. virtual bool init();
  21.  
  22. virtual void update(float dt);
  23. virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
  24. CREATE_FUNC(HelloWorld);
  25.  
  26. void initPhysics();
  27. void addNewSpriteAtPosition(cocos2d::Vec2 p);
  28.  
  29. };
  30.  
  31. #endif // __HELLOWORLD_SCENE_H__

上述代码第①行是引入头文件ContactListener.h。第②行代码是声明ContactListener类型的成员变量contactListener。

我们还须要改动HelloWorld.cpp中的HelloWorld::initPhysics()代码例如以下:

  1. void HelloWorld::initPhysics()
  2. {

  3. contactListener = new ContactListener();
  4. world->SetContactListener(contactListener);

  5. }

函数中的contactListener = new ContactListener()语句是创建ContactListener对象,採用了newkeyword分配内存,创建成员变量contactListener,须要自己释放contactListener对象。这些释放过程是在析构函数中进行。它的析构函数代码例如以下:
HelloWorld::~HelloWorld()
{
    CC_SAFE_DELETE(world);    
CC_SAFE_DELETE(contactListener);
}

使用CC_SAFE_DELETE(contactListener)安全释放contactListener成员变量的内存。

很多其它内容请关注最新Cocos图书《Cocos2d-x实战 C++卷》‍

本书交流讨论站点:http://www.cocoagame.net

很多其它精彩视频课程请关注智捷课堂Cocos课程:http://v.51work6.com
欢迎增加Cocos2d-x技术讨论群:257760386

《Cocos2d-x实战 C++卷》现已上线,各大商店均已开售:‍

京东:http://item.jd.com/11584534.html

亚马逊:http://www.amazon.cn/Cocos2d-x%E5%AE%9E%E6%88%98-C-%E5%8D%B7-%E5%85%B3%E4%B8%9C%E5%8D%87/dp/B00PTYWTLU

当当:http://product.dangdang.com/23606265.html

互动出版网:http://product.china-pub.com/3770734

《Cocos2d-x实战 C++卷》源代码及样章下载地址:

源代码下载地址:http://51work6.com/forum.php?mod=viewthread&tid=1155&extra=page%3D1

样章下载地址:http://51work6.com/forum.php?mod=viewthread&tid=1157&extra=page%3D1

欢迎关注智捷iOS课堂微信公共平台

实例介绍Cocos2d-x中Box2D物理引擎:碰撞检測的更多相关文章

  1. 实例介绍Cocos2d-x中Box2D物理引擎:HelloBox2D

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

  2. 实例介绍Cocos2d-x中Box2D物理引擎:使用关节

    下面我们将使用Box2D物理引擎技术进行重构.使得关节能够掌握如何在Box2D使用关节约束.HelloWorldScene.cpp中与使用关节的相关代码如下: void HelloWorld::add ...

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

    在Box2D中碰撞事件通过实现b2ContactListener类函数实现,b2ContactListener是Box2D提供的抽象类,它的抽象函数:virtual void BeginContact ...

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

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

  5. cocos2d-x中的Box2D物理引擎

    在Cocos2d-x中集成了2个物理引擎,一个是Chipmunk,一个是Box2D.前者是用C语言编写的,文档和例子相对较少:Box2D是用C++写的,并且有比较完善的文档和资料.所以在需要使用物理引 ...

  6. 瘸腿蛤蟆笔记29-cocos2d-x-3.2 Box2d物理引擎dynamics模块介绍

    转载标明出处:http://blog.csdn.net/notbaron/article/details/38611335 上篇回想 本篇名言:奋斗.寻觅.发现,而不屈服.[诗人丁尼生] 上篇中,我们 ...

  7. libgdx学习记录18——Box2d物理引擎

    libgdx封装了Box2D物理引擎,通过这个引擎能够模拟物理现实,使设计出的游戏更具有真实感. libgdx中,Box2d程序的大概过程: 1. 创建物理世界world,并设置重力加速度. 2. 创 ...

  8. python下的Box2d物理引擎的配置

    /******************************* I come back! 由于已经大四了,正在找工作 导致了至今以来第二长的时间内没有更新博客.向大家表示道歉 *********** ...

  9. 【极客学院出品】Cocos2d-X系列课程之九-BOX2D物理引擎

    Cocos2d-x 是时下最热门的手游引擎,在国内和国外手机游戏开发使用的份额各自是70%和25%,在App Store的top10中,有7个是用它开发的. 本节课程为Cocos2d-x系列课程之九, ...

随机推荐

  1. linux设置库文件加载包含路径

    第一种方式vim /etc/ld.so.conf 将要包含的路径添加到此文件中退出重新登录使配置生效或者执行命令source /etc/ld.so.conf 另一种方式利用LIBRARY_PATH和L ...

  2. [ SCOI 2005 ] 最大子矩阵

    \(\\\) \(Description\) 给出一个\(N\times M\)的有权矩阵,选出其中\(K\)个互不重叠的子矩阵,使得这\(K\)个子矩阵的权值和最大. \(N\in [1,100]\ ...

  3. dom4j.jar 的调试方法

    1.将jar包的路径写在 classpath下 在cmd窗口中,查看 classpath的内容是否已经加上该路径,win7 下cmd窗口一定要是管理员身份执行 2.在D盘新建一个DOM4JWriter ...

  4. 【sqli-labs】 less58 GET -Challenge -Double Query -5 queries allowed -Variation1 (GET型 挑战 双查询 只允许5次查询 变化1)

    单引号闭合成功,但是union select结果不对 http://192.168.136.128/sqli-labs-master/Less-58/?id=0' union select 1,2,3 ...

  5. Mock随机生成数据模拟后台接口

    <html> <head> <title>测试</title> <script src="http://code.jquery.com/ ...

  6. PHP采用301跳转方式防CC拦截

    PHP采用301跳转方式防CC拦截   降低CC攻击的效果 <?php empty($_SERVER['HTTP_VIA']) or exit('Access Denied'); $second ...

  7. (2)搜索广告CTR预估

    https://www.cnblogs.com/futurehau/p/6184585.html 1. CTR预估的流程 数据 -> 预处理 ->特征抽取 ->模型训练 ->后 ...

  8. Lua练习题集嚢

    --1.table.sort() am = {"cc","nn","ll","dd"} arr = function ( ...

  9. php第十八节课

    PDO 对不同的数据库连接使用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...

  10. 总结这几天js的学习内容

    对js中难点的理解 1.把变量对象像遍历数组一样简单 对于数组 ,迭代出来的是数组元素,对于对象 ,迭代出来的是对象的属性: var obj = { w: "wen", j: &q ...