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

好吧,事实上这篇也是暂时冒出来的,近期朋友要做个物理游戏,曾经做物理还是用box2d,呃。确实要花些功夫才干搞懂当中的精髓,可是听讲这套引擎又一次封装了一次。要easy非常多,所以就简单尝试了一下,感觉确实要简单不少,只是在这当中还是遇到了些问题,首先就来说说onContactBegin这个回调函数响应问题。

先说说情况。简单做了一个打砖块的游戏。前面一切都非常顺利,仅仅是做到碰撞检測的时候,发现回调函数弄死都不调用。開始我以为函数写错了,后来查了api。testCpp都没有错,在3.0的api中。没有关于PhysicsBody。PhysicsWorld这些类的说明。所以大家想查移步到3.2的api中吧。

onContactBegin函数的參数就一个,

bool onContactBegin(PhysicsContact& contact)。这和3.0beta版本号又有些不同,曾经是2个,所以在加入事件监听的时候,不要写错,like this。

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

回调函数是在当两个物体有接触的时候就会响应一次,里面的參数从名字中也能看出来,Contact接触,自然会涉及到两个物体。

好了。以下该到重点了,为啥这个onContactBegin函数不响应呢?问题出在三个掩码值上,这里推荐一下看下这篇博文

或者打开引擎的源码,能够在CCPhysicsShape这个头文件中看下这段代码,

/**
     * A mask that defines which categories this physics body belongs to.
     * Every physics body in a scene can be assigned to up to 32 different categories, each corresponding to a bit in the bit mask. You define the mask values used in your game. In conjunction with the collisionBitMask and contactTestBitMask properties, you define which physics bodies interact with each other and when your game is notified of these interactions.
     * The default value is 0xFFFFFFFF (all bits set).
     */
    inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; }
    inline int getCategoryBitmask() const { return _categoryBitmask; }
    
/**
     * A mask that defines which categories of bodies cause intersection notifications with this physics body.
     * When two bodies share the same space, each body’s category mask is tested against the other body’s contact mask by performing a logical AND operation. If either comparison results in a non-zero value, an PhysicsContact object is created and passed to the physics world’s delegate. For best performance, only set bits in the contacts mask for interactions you are interested in.
     * The default value is 0x00000000 (all bits cleared).
     */
    inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; }
    inline int getContactTestBitmask() const { return _contactTestBitmask; }
   
 /**
     * A mask that defines which categories of physics bodies can collide with this physics body.
     * When two physics bodies contact each other, a collision may occur. This body’s collision mask is compared to the other body’s category mask by performing a logical AND operation. If the result is a non-zero value, then this body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body. For example, you might use this to avoid collision calculations that would make negligible changes to a body’s velocity.
     * The default value is 0xFFFFFFFF (all bits set).
     */
    inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; }
    inline int getCollisionBitmask() const { return _collisionBitmask; }

说白了。两个物体间,能不能碰撞,能不能发送接触事件信息,关键就看这个三个參数值。

总结来说:

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

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

这三个參数都有自己的默认值。採用16位表示,

CategoryBitmask,        默认值为 0xFFFFFFFF

ContactTestBitmask,  默认值为 0x00000000

CollisionBitmask,        默认值为 0xFFFFFFFF

大家能够简单的算一下,假设对这个计算不了解,能够查查看哈,或者掏出你电脑上的计算器也能够哇。

依照前面的总结来说,假设我们创建的body都採用默认值的话。那么

CategoryBitmask & ContactTestBitmask = 0

CategoryBitmask & CollisionBitmask = -1

这样看来,情况就清楚了,假设採用默认的数值。碰撞是能够检測的。可是碰撞事件是不会发出的,so我们的onContactBegin就被屏蔽了,那么当然不会做事情。

所以假设想我们的两个物体即发生碰撞又能够检測到。那么非常easy,不让它们&的值不等于0就ok了。所以能够将两个须要碰撞的物体的这个三个掩码值都设置成1,

m_ball->getPhysicsBody()->setCategoryBitmask(0x01);
m_ball->getPhysicsBody()->setContactTestBitmask(0x01);
m_ball->getPhysicsBody()->setCollisionBitmask(0x01);
block->getPhysicsBody()->setCategoryBitmask(0x01);
block->getPhysicsBody()->setContactTestBitmask(0x01);
block->getPhysicsBody()->setCollisionBitmask(0x01);

这样它们之间怎么按位与的结果都是1。就能够有对应了。

bool HelloWorld::onContactBegin(PhysicsContact& contact)
{
	auto sp1 = (Sprite*)contact.getShapeA()->getBody()->getNode();
	auto sp2 = (Sprite*)contact.getShapeB()->getBody()->getNode();

	if (sp1->getTag() == 1)
		sp1->removeFromParentAndCleanup(true);
	if (sp2->getTag() == 1)
		sp2->removeFromParentAndCleanup(true);

	return true;
}

前面说了接触是肯定有两个物体的,所以打砖块的逻辑在这里就是推断下,当中一个的tag。假设是我们的砖块。说明碰到了。那么我们移除就ok了。

效果就是这样了。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdzMzNzE5ODMwMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

时间: 2024-08-26 18:07:23

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

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

好吧,其实这篇也是临时冒出来的,最近朋友要做个物理游戏,以前做物理还是用box2d,呃,确实要花些功夫才能搞懂其中的精髓,但是听讲这套引擎重新封装了一次,要容易很多,所以就简单尝试了一下,感觉确实要简单不少,不过在这其中还是遇到了些问题,首先就来说说onContactBegin这个回调函数响应问题. 先说说情况,简单做了一个打砖块的游戏,前面一切都很顺利,只是做到碰撞检测的时候,发现回调函数弄死都不调用.开始我以为函数写错了,后来查了api,testCpp都没有错,在3.0的api中,没有关于P

cocos2d-x 旅程開始--(实现瓦片地图中的碰撞检測)

转眼隔了一天了,昨天搞了整整一下午加一晚上,楞是没搞定小坦克跟砖头的碰撞检測,带着个问题睡觉甚是难受啊!还好今天弄成功了.只是感觉程序不怎么稳定啊.并且发现自己写的东西让我重写一遍的话我肯定写不出来.还要继续学习啊! 上次的进度: 实现了坦克的移动,昨天把程序优化了一下,能整合在一起的就整合在一个函数里了.并且对碰到屏幕边缘的情况进行了检測.之前的代码都是部分代码,今天试试把代码整个贴上去. 这两天的进度: 打这么多汉字,自个都看不进去.直接上代码: /////////////////////实

Cocos2d-x3.0游戏实例之《别救我》第七篇——物理世界的碰撞检測

事实上我也非常吃惊-居然写到第七篇了,我估计也就是四篇的内容,感觉非常奇妙,我也不会非常唠叨什么吖(小若:32个喷! ),怎么都到第七篇了. 笨木头花心贡献,啥?花心?不呢,是用心~ 转载请注明,原文地址: http://www.benmutou.com/blog/archives/920 文章来源:笨木头与游戏开发 碰撞监听 首先,确保我们创建物理对象的时候,给对象设置了碰撞条件(假设你是一步步按着教程来写的代码,那就是设置好了): body->setCategoryBitmask(1);  

Cocos2d-x碰撞检測

假设不适用Box2D物理引擎.那么要进行Cocos2d-x的碰撞检測那我们的方法往往就是进行"矩形和点"."矩形和矩形"这样粗略的碰撞检測.我们一般採取开启scheduleUpdate定时器.然后重写update函数进行每一帧都进行碰撞检測. <1>碰撞检測的代码较为繁琐.恕我无法为你具体列出其思路能够是在update中遍历全部的sprite, 然后推断每一个sprite和其它sprite(还需遍历一遍.刨除自己)是否碰撞. 这样等于推断次数是sprit

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

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

Unity3D入门(二):碰撞检測

碰撞器由来 1.系统默认会给每一个对象(GameObject)加入?一个碰撞组件(ColliderComponent),一些背景对象则能够取消该组件. 2.在unity3d中,能检測碰撞发生的方式有两种,一种是利用碰撞器,还有一种则是利用触发器.这两种方式的应用很广泛.为了完整的了解这两种方式,我们必须理解下面概念: (一)碰撞器是一群组件,它包括了非常多种类,比方:Box Collider,Capsule Collider等,这些碰撞器应用的场合不同,但都必须加到GameObjecet身上.(

cocos2d-x ios游戏开发初认识(八) 触摸事件与碰撞检測

玩过植物大战僵尸都知道,要在草坪里放一朵向日葵或者其他的植物仅仅需触摸那个植物将其拖入到想要摆放的位置,这事实上就是这节要写的触摸事件.还能够发现当我们的僵尸出来的时候,我们的小豌豆会发子弹攻击僵尸,当子弹与僵尸碰撞的时候子弹自己主动消失,这就这节要说的碰撞检測. 以下详细看代码的实现: 做ios开发有触摸事件cocos2d相同也有 一.先覆写touch事件 .h文件 using namespace cocos2d; class MainScene:public CCLayer { privat

cocos2d-html5 碰撞检測的几种方法

游戏中的碰撞还是比較多的,比方角色与角色的碰撞,角色与墙壁的碰撞,角色与怪物的碰撞等,都须要 进行碰撞的检測,来触发一定的事件 近期在尝试制作一个小游戏的时候须要用到碰撞检測,然后就查了下资料,并在论坛进行提问等算是找到了比較惬意的碰撞检測方法,这里记录下来 如今自己知道的方法算是有了三种了,以下一一记录并分析下他们各自的优缺点 1.就是官方提供的,依据getBoundingBox();方法获取要检測的碰撞物体的范围,然后再依据rectIntersectsRect();方法进行推断须要检測的两个

iOS 碰撞检測以及事件响应

*/ //碰撞检測 //碰撞检測de过程 //碰撞检測 //碰撞检測 //碰撞检測 //UIApplication-> UIWindow-> UIController-> 视图控制器view-> 父视图 ->子视图 //事件响应 //事件响应de过程 //事件响应 //事件响应 //事件响应 //反方向处理;UIApplication <- UIWindow <- UIController <- 视图控制器view <- 父视图 <- 子视图;