cocos2d-x-3.3-021-碰撞检测3-物理引擎碰撞过滤

原文同步发布于我的wiki,查看原文或更新请移步: 点击打开链接

引子

  • 上一篇简单演示了如何使用物理引擎以及用它来作碰撞监测。但有问题,那就是敌人和敌人也会发生碰撞,子弹和子弹之间也会发生碰撞。。。要解决这个问题(避免不必要的碰撞,或碰撞过滤),得先看看cocos封装物理引擎后给我们提供的API。

?

PhysicsBody相关API说明

  • void setGroup(int group);
      Collision groups let you specify an integral group index.
You can have all fixtures with the same group index always collide
(positive index) or never collide (negative index)
      it have high priority than bit masks

PhysicsBody的Group
1.优先级比bit masks的优先级高(CategoryBitmask,ContactTestBitmask,CollisionBitmask)
2.group是正数且相等的话,就一定碰撞
3.group是负数且相等的话,就一定不会碰撞
4.group其他情况没说,应该是取决于bit masks了
  • void setCategoryBitmask(int bitmask);
      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).

PhysicsBody的CategoryBitmask
1.CategoryBitmask用来标记这个PhysicsBody的所属类别
2.每个PhysicsBody最多可以属于32个类别,一个bit代表一个类别,0代表不是对应类别,1代表是对应类别
3.和另外两个属性(collisionBitMask and contactTestBitMask)配合着用
4.默认值0xFFFFFFFF,即这个PhysicsBody分别属于所有的32个类别
  • void setContactTestBitmask(int bitmask);
      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).

PhysicsBody的ContactTestBitmask
1.ContactTestBitmask用来定义哪个类别的PhysicsBody可以和这个PhysicsBody产生相交通知
2.举个例子:有PhysicsBody A B占了同样的空间了。如何判断A B要产生相交通知呢,
if((A.CategoryBitmask & B.ContactTestBitmask) != 0 || (A.ContactTestBitmask & B.CategoryBitmask) != 0)
    {/*条件成立,执行相交通知*/}
else{/*没有相交通知*/}
3.为了性能考虑,相交通知只应该设置给我们感兴趣的物体
4.默认值0x00000000 (all bits cleared),没有哪个类别的PhysicsBody可以产生相交通知
  • void setCollisionBitmask(int bitmask);
      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).

PhysicsBody的CollisionBitmask
1.CollisionBitmask是用来定义哪个类别的PhysicsBody可以和这个PhysicsBody产生碰撞
2.举个例子:有PhysicsBody A B彼此接触了,那碰撞就可能发生。
A受不受这个碰撞的影响(体现为物理效果)表达为:
if((A.CollisionBitmask & B.CategoryBitmask) != 0 ){/*A产生碰撞的物理效果*/}
else{/*A没效果*/}
3.至于B受不受这个碰撞的影响,则采用同样的表达式单独计算即可
if((B.CollisionBitmask & A.CategoryBitmask) != 0 ){/*B产生碰撞的物理效果*/}
else{/*B没效果*/}
4.默认值0xFFFFFFFF (all bits set),所有类别的PhysicsBody都能对this body产生碰撞效果

DEMO及源码

  • 基于cocos 3.4final
  • DEMO功能:注册了物理碰撞事件的监听,用来查看是否有事件回调;注册了touch事件监听,在touch的结束事件里回在触摸点创建一个带物理效果的精灵。精灵有两种,用来测试PhysicsBody的设置造成的影响。具体看代码,不复杂。
  • https://github.com/cheyiliu/CollisionDetection

验证对API的理解

所有参数保持默认

属性值:
group             =0
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000000
CollisionBitmask  =0xFFFFFFFF

  • 现象和分析:

    1. a b为同一类物品,有碰撞现象【group未设置; 那就套上面的API的分析,(a.CategoryBitmask
      & b.CollisionBitmask) != 0
       true; 反过来也是; 故a b都有碰撞效果。】
    2. a b为同一类物品,无碰撞回调【套公式 ((a.CategoryBitmask
      & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)
      等于false,故没回调。】

确认group优先级

属性值:
group             =需要设置<-----
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000000
CollisionBitmask  =0xFFFFFFFF

  • 现象和分析:

    1. a b为同一类物品,group都取1。有碰撞现象,无回调【跟group不设置时现象一样,还不能说明什么】
    2. a b为同一类物品,group都取-1。无碰撞现象,无回调,物体a b分别从同一个位置落下后,a b重叠【其他bitmask的默认值设置是有碰撞现象的,但设置group取相同的负数后没碰撞了,group优先级高!】
    3. a b为同一类物品,group都取1,但设置CollisionBitmask=0x00(试图不要碰撞效果)。现象1自由落体到世界外面去了,现象2快速touch在同一个位置产生两个精灵会有挤开的现象(若group取-1则不会挤开,叠在一起了)。【说明group的优先级最高!】
    4. a b为同一类物品,group都取1,但设置CollisionBitmask=0x00(试图不要碰撞效果),设置ContactTestBitmask=0x01(试图获取回调)。现象1自由落体到世界外面去了;现象2快速touch在同一个位置产生两个精灵会有挤开的现象(若group取-1则不会挤开,叠在一起了);现象3有回调。【说明group的优先级最高!】

想要回调

属性值:
group             =0
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000001<-----change to this
CollisionBitmask  =0xFFFFFFFF

  • 现象和分析:

    1. a b为同一类物品,有碰撞现象,有回调【碰撞的理由是(a.CollisionBitmask
      & b.CategoryBitmask) != 0
      非0, true;有回调的理由是((a.CategoryBitmask
      & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)
       等于true】

想要回调但不要碰撞效果

属性值:
group             =0
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0x00000001<-----change to this
CollisionBitmask  =0x00000000<-----change to this

  • 现象和分析:

    1. a b为同一类物品,无碰撞现象,无回调【不碰撞的理由是(a.CollisionBitmask
      & b.CategoryBitmask) != 0
       等于0,false,;无回调的理由是虽然((a.CategoryBitmask
      & b.ContactTestBitmask) != 0|| (a.ContactTestBitmask & b.CategoryBitmask) != 0)
       等于true,但是没有碰撞的前提】

想要A类和B类碰撞,A类之间不碰撞,B类之间不碰撞-法1

属性值:
group             =0【A的group取-1;B的group取-2】
CategoryBitmask   =0xFFFFFFFF
ContactTestBitmask=0xFFFFFFFF【AB都取这个值】
CollisionBitmask  =0xFFFFFFFF

  • 现象和分析:

    1. 同类之间不碰撞,a b为同一类物品【group决定的,相同的负的group值的对象不会碰撞;虽然((a.CategoryBitmask
      & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)
      等于true,但没碰撞的前提,故无回调】
    2. 不同类可以碰撞,a b为不同类的物品【group的值不一样,取决于bitmask了;碰撞的理由是(a.CollisionBitmask
      & b.CategoryBitmask) != 0
      非0,true,b也是;回调理由是有碰撞且((a.CategoryBitmask
      & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)
       等于true】

想要A类和B类碰撞,A类之间不碰撞,B类之间不碰撞-法2

属性值:
group             =0【AB都保持默认0】
CategoryBitmask   =【A的CategoryBitmask=0x01;B的CategoryBitmask=0x02】
ContactTestBitmask=【A的ContactTestBitmask=0x02;B的ContactTestBitmask=0x01】
CollisionBitmask  =【A的CollisionBitmask=0x02;B的CollisionBitmask=0x01】

  • 现象和分析:

    1. 同类之间无碰撞,a b为同一类物品【无碰撞的理由是(a.CollisionBitmask
      & b.CategoryBitmask) != 0
      false; 无回调是((a.CategoryBitmask
      & b.CollisionBitmask) != 0 || (a.CollisionBitmask & b.CategoryBitmask) != 0)
      等于false故无回调】
    2. 不同类可以碰撞,a b为不同类的物品【碰撞的理由是(a.CollisionBitmask
      & b.CategoryBitmask) != 0
      true,b也是;回调理由是有碰撞且((a.CategoryBitmask
      & b.ContactTestBitmask) != 0 || (a.ContactTestBitmask & b.CategoryBitmask) != 0)
      等于true】

效果图

  • 想要A类和B类碰撞,A类之间不碰撞,B类之间不碰撞(NOTE: gif中,相同的图片是同一类,不同图片类型不同)
  • https://github.com/cheyiliu/All-in-One/raw/master/res/cocos2d/CollisionDetection-way3-use-physics-engine-filter.gif

总结

  • 能碰撞,不能碰撞以及碰撞事件通知的大致逻辑
PhysicsBody a;
PhysicsBody b;

if ((a.group == b.group) && a.group > 0) {
    /*能碰撞,有碰撞的物理效果*/
    if (((a.CategoryBitmask & b.ContactTestBitmask) != 0)
            || ((a.ContactTestBitmask & b.CategoryBitmask) != 0)) {
        /*条件成立,执行相交通知*/
    }
} else if ((a.group == b.group) && a.group < 0) {
    /*不能碰撞,没有碰撞的物理效果*/
} else {
    if ((a.CollisionBitmask & b.CategoryBitmask) != 0) {
        /*a能碰撞,a有碰撞的物理效果*/
        if (((a.CategoryBitmask & b.ContactTestBitmask) != 0)
                || ((a.ContactTestBitmask & b.CategoryBitmask) != 0)) {
            /*条件成立,执行相交通知*/
        }
    } else {
        /*a不能碰撞,a没有碰撞的物理效果*/
    }

    if ((b.CollisionBitmask & a.CategoryBitmask) != 0) {
        /*b能碰撞,b有碰撞的物理效果*/
        if (((a.CategoryBitmask & b.ContactTestBitmask) != 0)
                || ((a.ContactTestBitmask & b.CategoryBitmask) != 0)) {
            /*条件成立,执行相交通知*/
        }
    } else {
        /*b不能碰撞,b没有碰撞的物理效果*/
    }

}
时间: 2024-08-01 06:36:13

cocos2d-x-3.3-021-碰撞检测3-物理引擎碰撞过滤的相关文章

【Unity 3D】学习笔记三十七:物理引擎——碰撞与休眠

碰撞与休眠 上一篇笔记说过,当给予游戏对象刚体这个组件以后,那么这个组件将存在碰撞的可能性.一旦刚体开始运动,那么系统方法便会监视刚体的碰撞状态.一般刚体的碰撞分为三种:进入碰撞,碰撞中,和碰撞结束.关于休眠可以理解成为让游戏对象变成静止状态.如果给某个游戏对象休眠的状态,那么这个物体将立马静止,不再运动. 碰撞 首先学习下碰撞几个重要的方法: OnCollisionEnter(  ):刚体开始接触的时候,立即调用. OnCollisionStay(  ):碰撞过程中,每帧都会调用此方法,直到撞

SpriteKit物理引擎碰撞中5个重要信息

我们知道在SpriteKit物理引擎实际是基于Box2D! 在SpriteKit中当你设置好适当的碰撞参数后,通过遵守SKPhysicsContactDelegate,你可以选择实现2各碰撞回调方法: didBeginContact didEndContact 方法中会传递一个参数,其类型为SKPhysicsContact,其中含有5个非常重要的碰撞信息,下面分别介绍一下: bodyA 类型为SKPhysicsBody,表示第一个碰撞接触对象 bodyB 类型同上,表示第二个碰撞对象 conta

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

碰撞检测是使用物理引擎的一个重要目的,使用物理引擎可以进行精确的碰撞检测,而且执行的效率也很高.在Cocos2d-x 3.x中使用事件派发机制管理碰撞事件,EventListenerPhysicsContact是碰撞事件监听器.碰撞检测相关的API我们在前面一节介绍过了,下面通过一个实例介绍碰撞检测的实现.这个实例的运行后的场景如图所示,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一个新的精灵,精灵的运行是自由落体运动.当这些精灵之间发生接触时候,它们的颜色被设置为黄色,分

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

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

Cocos2d-x 使用物理引擎进行碰撞检测

[转自]: http://blog.csdn.net/cbbbc/article/details/38541099 通常在游戏简单逻辑判断和模拟真实的物理世界时,我们只需要在定时器中判断游戏中各个精灵的条件是否满足判断条件就可以了.例如,在飞机大战中,判断我方子弹和敌机是否发生碰撞一般在定时器中通过敌机所在位置的矩形是否包括了子弹的位置来判断是否发生碰撞.在消除类游戏中,判断在y轴或x轴上是否要消除相同物品一般在定时器中通过循环来检测在某个方向上是否有连续的相同物品满足消除个数来移除精灵就可以了

物理引擎中不规则物体的碰撞检测

在运用物理引擎的时候,经常回出现这种情况,不规则物体的碰撞检测无法更加精确的测量,那么,小杰今天就带您一起解决这个问题!!! 首先下载一个windows下面的软件 名称是:PhysicsEditor ,这个软件可以帮助你设计不规则的图形.软件的使用方法在这里不具体讲解了,说一下注意的问题,添加进精灵后 :按照这个步骤走 好了,这时候 做完了就会生成 plist文件,把它和png图片一起拷进资源目录下面: 定义一个成员方法: std::vector<std::vector<Vec2>>

Unity3D实践系列09, 物理引擎与碰撞检测

在Unity3D中,一个物体通常包含一个Collider和一个Rigidbody.Collider是碰撞体,一个物体是Collider,才可以进行碰撞检测.Collider组件中的"Is Trigger"属性项被勾选上时,这个物体就变成碰撞检测体. 物体有了Rigidbody组件,才会具备一些物理属性,比如重量.阻力.旋转阻力,等等."Use Gravity"项表示是否有自然引力."Is Kinematic"项表示是否被物理引擎所驱动,勾选上表示

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

我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用物理引擎的开发过程,熟悉这些API的使用.这个实例的运行后的场景,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一个新的精灵,精灵的运行是自由落体运动. HelloPhysicsWorld实例 使用物理引擎的一般步骤,如下图所示. 这个过程与上帝创建世界的过程类似,上帝首先创建了世界,然后为世界指定了边界,否则万物就会掉到世界之外的混沌里去了,最后上帝创建了万物.当然这只是一个最基本的步骤,有的时候还需要碰撞检测和使

转:Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 前言 Bullet据称为游戏世界占有率为第三的物理引擎,也是前几大引擎目前唯一能够找到的支持iPhone,开源,免费(Zlib协议,非常自由,且商业免费)的物理引擎,但是文档资料并不是很好,Demo虽然多,但是主要出于特性测试/展示的目的,会让初学者无从看起,一头雾水.我刚学习Bullet的时候困于没有好的文档及资料,非常没有头绪,折腾了很久,所以就发挥没有就创造的精神,写作及整

Cocos2d-js官方完整项目教程翻译:六、添加Chipmunk物理引擎在我们的游戏世界里

添加Chipmunk物理引擎在我们的游戏世界里         一.简介                   cocos2d JS能给我们力量来创造令人印象深刻的游戏世界.但缺乏某种现实.          虽然我们可以做复杂的计算,使游戏世界更真实的,但有另一个选择          它可以缓解我们的生活.答案是物理引擎.          物理引擎提供了重力,碰撞检测和物理模拟,可以使我们的游戏世界看起来更真实.          在本教程中,我们将介绍的ChipMunk的物理引擎进入我们的