• Cocos Creator碰撞系统

    2019-01-11 11:38:43
    Cocos Creator 有两套碰撞系统,其中常用的是物理系统 点击添加组件。物体系统 在要发生碰撞的两个物体身上都添加这组件 这是物理系统添加的刚体组件 1 为是否开启监听事件 如果不开启 没办法监听碰撞回调 2 是...

    Cocos Creator 有两套碰撞系统,其中常用的是物理系统
    点击添加组件。物体系统
    在这里插入图片描述
    在要发生碰撞的两个物体身上都添加这个组件
    在这里插入图片描述
    这是物理系统添加的刚体组件
    1 为是否开启监听事件 如果不开启 没办法监听碰撞回调
    2 是防止物理穿透
    Allow Sleep 默认为true 就是指物体只会发生一次碰撞
    剩下的不多做解释
    在这里插入图片描述
    使用物理碰撞盒的时候 ,为了使碰撞看起来更加流畅,要修改一下弹性系数,数值视情况而定(数值范围为0~1 数值越大,物体碰撞后发生的反弹现象越明显)
    接下来就是要在脚本里开启物理系统(如果不开启物理系统,不会产生物理效果,物理系统只用开启一次)

    onLoad () {
             //开启物理系统
             cc.director.getPhysicsManager().enabled = true;
        },
    

    然后使用碰撞回调的方法写出相对操作

    // 只在两个碰撞体开始接触时被调用一次
        onBeginContact: function (contact, selfCollider, otherCollider) {
          console.log('有人碰到了玩家');
        },
    
        // 只在两个碰撞体结束接触时被调用一次
        onEndContact: function (contact, selfCollider, otherCollider) {
        },
    
        // 每次将要处理碰撞体接触逻辑时被调用
        onPreSolve: function (contact, selfCollider, otherCollider) {
            
        },
        // 每次处理完碰撞体接触逻辑时被调用
        onPostSolve: function (contact, selfCollider, otherCollider) {
            
        }
    
    展开全文
  • cocos2dx碰撞检测算法

    2016-09-12 15:37:29
    Cocos2d-x 3.x版本添加了对3D物体的支持后,3D物体碰撞检测方法也随之更新,其中一种最简单的碰撞检测方法就是AABB碰撞检测。1.AABB包围盒在游戏中,为了简化物体之间的碰撞检测运算,通常会对物体创建一规则...

    在Cocos2d-x 3.x版本添加了对3D物体的支持后,3D物体的碰撞检测方法也随之更新,其中一种最简单的碰撞检测方法就是AABB碰撞检测。


    1.AABB包围盒

    在游戏中,为了简化物体之间的碰撞检测运算,通常会对物体创建一个规则的几何外形将其包围。

    其中,AABB(axis-aligned bounding box)包围盒被称为轴对其包围盒。

    二维场景中的AABB包围盒具备特点:(注:由于Cocos2d-x是基于Opengl ES的,所以下图中的所有坐标系均采用右手直角坐标系)

    (1) 表现形式为四边形,即用四边形包围物体。

    (2) 四边形的每一条边,都会与坐标系的轴垂直。

    如图 1-1 所示:

    图1-1

    三维场景中的AABB包围盒特点:

    (1) 表现形式为六面体。

    (2) 六面体中的每条边都平行于一个坐标平面。

    如图 1-2 所示:

    图 1-2(图片来源百度)

    在图1-2中,为了更明显的展示AABB包围盒的特点,在最右侧展示了一个OBB(Oriented Bounding Box)包围盒,也称作有向包围盒。

    可以看出,AABB包围盒与OBB包围盒的最直接的区别就是,AABB包围盒是不可以旋转的,而OBB包围盒是可以旋转的,也就是有向的。


    2. 二维场景中的AABB碰撞检测原理

    首先来看一张二维场景中的物体碰撞图:

    图 2-1

    在图 2-1中,分别做物体A与物体B在X,Y轴方向的投影,物体A的Y轴方向最大点坐标为Y1,最小点坐标Y2,X轴方向最小点坐标X1,最大点坐标X2,物体B同理。

    图中红色区域为物体A与物体B投影的重叠部分。

    可以看出,AABB碰撞检测具有如下规则:

    物体A与物体B分别沿两个坐标轴做投影,只有在两个坐标轴都发生重叠的情况下,两个物体才意味着发生了碰撞。

    所以,在程序中做二维游戏的AABB碰撞检测时,只需验证物体A与物体B是否满足如下条件:

    (1)物体A的Y轴方向最小值大于物体B的Y轴方向最大值;

    (2)物体A的X轴方向最小值大于物体B的X轴方向最大值;

    (3)物体B的Y轴方向最小值大于物体A的Y轴方向最大值;

    (4)物体B的X轴方向最小值大于物体A的X轴方向最大值;

    若满足上述条件,则证明物体A与物体B并未发生重合,反之,则证明物体A与物体B重合。


    3. 三维场景中的AABB碰撞检测原理

    首先,再来看一下图2-1中的二维物体A和物体B的包围盒,可以发现实际上判断物体A与物体B是否发生重合只需要知道两个信息:

    (1) 物体A的最小点的信息,即图2-1中A的左下角点;以及物体A的最大点的信息,即图2-1中A的右上角点。

    (2) 物体B的最小点的信息,物体B的最大点的信息。

    也就是说在二维场景的碰撞检测中,每个物体的顶点坐标信息都可以由两个坐标来确定,即两个坐标就可以标识一个物体了,所以两个物体的碰撞检测只需要获得到四个点坐标就可以了。

    之前在图1-2中已经看到,三维场景中物体的AABB包围盒是一个六面体,其坐标系对于二维坐标系来讲只是多了一个Z轴,所以实际上在三维场景中物体的AABB碰撞检测依然可以采用四个点信息的判定来实现。即从物体A的八个顶点与物体B的八个顶点分别选出两个最大与最小的顶点进行对比。三维物体的AABB包围盒的八个顶点依旧可以用两个顶点来标识,如图 3-1 所示:

    图3-1

    只要确定了图中黑色点部分的坐标,就可以确定八个顶点的全部信息了。

    在Cocos2d-x 3.x版本中,为开发者提供了AABB类,用于保存包围盒的最大顶点与最小顶点的信息,并且为每个Sprite3D对象提供了获取AABB包围盒的接口,在AABB类同时提供了判断相应的碰撞检测的方法。

    下面对AABB的源码进行分析:

    CCAABB.h 文件

    CCAABB.cpp 文件


    4. 总结

    最后,AABB碰见庄策算法虽然计算方法简单,速度快,但是仅适用于精度不搞的游戏中。相对于AABB碰撞检测,还有一种更逼近物体并更为精确的一种算法——OBB碰撞检测。在Cocos2d-x 中同样提供了OBB碰撞检测的相应方法,如图 4-1所示:
    图 4-1

    原文出处 :http://blog.csdn.net/u012945598/article/details/38870705

    展开全文
  • ![图片说明](https://img-ask.csdn.net/upload/201806/30/1530350141_893295.png)
  • 刚从unity转到creator 用的的TS语言 物体要具有**物理碰撞效果**,添加组件- 物理组件-...物体碰撞进入此函数 在creator中没有触发函数,但有一属性 类似unity的触发效果(解释为进入碰撞回调但不具有物理...

    刚从unity转到creator
    用的的TS语言

    物体要具有**物理碰撞效果**,添加组件- 物理组件-collider-boxcollider 会自动加上rigibody组件

    creator中默认碰撞是关闭的,需要自己手动开启`此方法一定要写到onLoad生命周期中
    

    在这里插入图片描述
    物体碰撞进入此函数
    在这里插入图片描述
    在creator中没有触发函数,但有一个属性 类似unity的触发效果(解释为进入碰撞回调但不具有物理碰撞效果
    在这里插入图片描述
    如果两个物体相碰撞想要获取 碰撞信息,例如;**物体碰撞点、两个物体的碰撞速度、碰撞轨迹方向**
    这个points返回的是一个向量数组, points[0]就是第一个碰撞点
    在这里插入图片描述
    获得刚体上指定点的线性速度(这里传入的是碰撞点
    在这里插入图片描述
    获得物体碰撞后的轨迹方向
    在这里插入图片描述
    碰撞物体的线性速度,这个获取到的是物体的线性速度,得到的是一个向量
    在这里插入图片描述
    如果要比较物体的速度,需要把线性速度向量求模 获得number类型的值,比较两个物体速度大小
    creator 我没发现求模的函数,vector2.magititute ,只能自己计算,向量的(xx+yy)开根
    在这里插入图片描述

    这些信息就是 物体碰撞的基本信息了

    新手入坑,有不对的地方,请指教!

    展开全文
  • Cocos2d-x 3.x版本 3D物体碰撞检测,AABB包围盒。


    欢迎加入Cocos2d-x 交流群:193411763


    转载时请注明原文出处 :http://blog.csdn.net/u012945598/article/details/39524343


    -----------------------------------------------------------------------------------------------------------------------------------------------------------


    在Cocos2d-x 3.x版本添加了对3D物体的支持后,3D物体的碰撞检测方法也随之更新,其中一种最简单的碰撞检测方法就是AABB碰撞检测。


    1. AABB包围盒

            在游戏中,为了简化物体之间的碰撞检测运算,通常会对物体创建一个规则的几何外形将其包围。

            其中,AABB(axis-aligned bounding box)包围盒被称为轴对其包围盒。


            二维场景中的AABB包围盒具备特点:(注:由于Cocos2d-x是基于Opengl ES的,所以下图中的所有坐标系均采用右手直角坐标系)


           (1) 表现形式为四边形,即用四边形包围物体。

           (2) 四边形的每一条边,都会与坐标系的轴垂直。


            如图 1-1 所示:

          

               图1-1


             三维场景中的AABB包围盒特点:


           (1) 表现形式为六面体。

           (2) 六面体中的每条边都平行于一个坐标平面。

         

            如图 1-2 所示:

         

    图 1-2(图片来源百度)

         

            在图1-2中,为了更明显的展示AABB包围盒的特点,在最右侧展示了一个OBB(Oriented Bounding Box)包围盒,也称作有向包围盒。

            可以看出,AABB包围盒与OBB包围盒的最直接的区别就是,AABB包围盒是不可以旋转的,而OBB包围盒是可以旋转的,也就是有向的。


    2. 二维场景中的AABB碰撞检测原理

            首先来看一张二维场景中的物体碰撞图:

         

    图 2-1


            在图 2-1中,分别做物体A与物体B在X,Y轴方向的投影,物体A的Y轴方向最大点坐标为Y1,最小点坐标Y2,X轴方向最小点坐标X1,最大点坐标X2,物体B同理。

            图中红色区域为物体A与物体B投影的重叠部分。


            可以看出,AABB碰撞检测具有如下规则:

            物体A与物体B分别沿两个坐标轴做投影,只有在两个坐标轴都发生重叠的情况下,两个物体才意味着发生了碰撞。

            

            所以,在程序中做二维游戏的AABB碰撞检测时,只需验证物体A与物体B是否满足如下条件:

            (1)物体A的Y轴方向最小值大于物体B的Y轴方向最大值;

            (2)物体A的X轴方向最小值大于物体B的X轴方向最大值;

            (3)物体B的Y轴方向最小值大于物体A的Y轴方向最大值;

            (4)物体B的X轴方向最小值大于物体A的X轴方向最大值;

            若满足上述条件,则证明物体A与物体B并未发生重合,反之,则证明物体A与物体B重合。


    3. 三维场景中的AABB碰撞检测原理

           首先,再来看一下图2-1中的二维物体A和物体B的包围盒,可以发现实际上判断物体A与物体B是否发生重合只需要知道两个信息:

           (1) 物体A的最小点的信息,即图2-1中A的左下角点;以及物体A的最大点的信息,即图2-1中A的右上角点。

           (2) 物体B的最小点的信息,物体B的最大点的信息。

           也就是说在二维场景的碰撞检测中,每个物体的顶点坐标信息都可以由两个坐标来确定,即两个坐标就可以标识一个物体了,所以两个物体的碰撞检测只需要获得到四个点坐标就可以了。


           之前在图1-2中已经看到,三维场景中物体的AABB包围盒是一个六面体,其坐标系对于二维坐标系来讲只是多了一个Z轴,所以实际上在三维场景中物体的AABB碰撞检测依然可以采用四个点信息的判定来实现。即从物体A的八个顶点与物体B的八个顶点分别选出两个最大与最小的顶点进行对比。三维物体的AABB包围盒的八个顶点依旧可以用两个顶点来标识,如图 3-1 所示:

                 

    图3-1


            只要确定了图中黑色点部分的坐标,就可以确定八个顶点的全部信息了。


            在Cocos2d-x 3.x版本中,为开发者提供了AABB类,用于保存包围盒的最大顶点与最小顶点的信息,并且为每个Sprite3D对象提供了获取AABB包围盒的接口,在AABB类同时提供了判断相应的碰撞检测的方法。有一点需要注意的是,CCAABB类中一开始保存的最大顶点与最小顶点的信息实际上是物体坐标系中的信息,而实际上在碰撞检测时需要将其转换成世界坐标系中的点,这一过程在Sprite3D中的getAABB()方法中实现,可通过CCAABB中的

    transform()方法来完成。


            下面对AABB的源码进行分析:


            CCAABB.h 文件

           

    class CC_3D_DLL AABB
    {
    
    public:
        /**
         * 构造函数
         */
        AABB();
        
        /**
         * 构造函数 参数:最小顶点坐标,最大顶点坐标
         */
        AABB(const Vec3& min, const Vec3& max);
        
        /**
         * 构造函数 参数:AABB包围盒
         */
        AABB(const AABB& box);
        
        /**
         * 获取包围盒中心点坐标
         */
        Vec3 getCenter();
        
        /* 获取包围盒八个顶点信息
         * Z轴正方向的面
         * verts[0] : 左上顶点
         * verts[1] : 左下顶点
         * verts[2] : 右下顶点
         * verts[3] : 右上顶点
         *
         * Z轴负方向的面
         * verts[4] : 右上顶点
         * verts[5] : 右下顶点
         * verts[6] : 左下顶点
         * verts[7] : 左上顶点
         */
        void getCorners(Vec3 *dst) const;
    
        /**
         * 判断两个包围盒是否重合
         */
        bool intersects(const AABB& aabb) const;
    
        /**
         * 判断一个点是否在包围盒内
         */
        bool containPoint(const Vec3& point) const;
    
        /**
         由两个包围盒生成一个能同时包围这两个包围盒的最小包围盒
         */
        void merge(const AABB& box);
    
        /**
         * 设置包围盒的最大顶点与最小顶点
         */
        void set(const Vec3& min, const Vec3& max);
        
        /**
         * 复位函数 初始化最大最小顶点信息
         */
        void reset();
        
        bool isEmpty() const;
    
        /**
         * 更新最大顶点与最小顶点信息
         */
        void updateMinMax(const Vec3* point, ssize_t num);
        
        /**
         * 由一个矩阵对对包围盒进行顶点变换
         */
        void transform(const Mat4& mat);
    
    public:
        Vec3 _min;   //三维向量 保存最小点坐标
        Vec3 _max;   //三维向量 保存最大点坐标
    };
    
    NS_CC_END
    
         
         
           CCAABB.cpp 文件
           
           
    #include "3d/CCAABB.h"
    
    NS_CC_BEGIN
    
    //构造函数
    AABB::AABB()
    {
        reset(); //初始化最大顶点与最小顶点
    }
    
    AABB::AABB(const Vec3& min, const Vec3& max)
    {
        set(min, max); //设置最大顶点与最小顶点
    }
    
    AABB::AABB(const AABB& box)
    {
    	set(box._min,box._max); //设置最大顶点与最小顶点
    }
    //获取包围盒中心点坐标
    Vec3 AABB::getCenter()
    {
        Vec3 center;
    	center.x = 0.5f*(_min.x+_max.x);
    	center.y = 0.5f*(_min.y+_max.y);
    	center.z = 0.5f*(_min.z+_max.z);
    
        return center;
    }
    //获取包围盒八个顶点信息
    void AABB::getCorners(Vec3 *dst) const
    {
        assert(dst);
        
        // 朝着Z轴正方向的面
        // 左上顶点坐标
        dst[0].set(_min.x, _max.y, _max.z);
        // 左下顶点坐标
        dst[1].set(_min.x, _min.y, _max.z);
        // 右下顶点坐标
        dst[2].set(_max.x, _min.y, _max.z);
        // 右上顶点坐标
        dst[3].set(_max.x, _max.y, _max.z);
    
        // 朝着Z轴负方向的面
        // 右上顶点坐标
        dst[4].set(_max.x, _max.y, _min.z);
        // 右下顶点坐标
        dst[5].set(_max.x, _min.y, _min.z);
        // 左下顶点坐标
        dst[6].set(_min.x, _min.y, _min.z);
        // 左上顶点坐标
        dst[7].set(_min.x, _max.y, _min.z);
    }
    //判断两个包围盒是否碰撞
    bool AABB::intersects(const AABB& aabb) const
    {
        return ((_min.x >= aabb._min.x && _min.x <= aabb._max.x) || (aabb._min.x >= _min.x && aabb._min.x <= _max.x)) &&
               ((_min.y >= aabb._min.y && _min.y <= aabb._max.y) || (aabb._min.y >= _min.y && aabb._min.y <= _max.y)) &&
               ((_min.z >= aabb._min.z && _min.z <= aabb._max.z) || (aabb._min.z >= _min.z && aabb._min.z <= _max.z));
    }
    //判断点和包围盒是否碰撞
    bool AABB::containPoint(const Vec3& point) const
    {
    	if (point.x < _min.x) return false;
    	if (point.y < _min.y) return false;
    	if (point.z < _min.z) return false;
    	if (point.x > _max.x) return false;
    	if (point.y > _max.y) return false;
    	if (point.z > _max.z) return false;
    	return true;
    }
    //生成一个新的包围盒 同时容纳两个包围盒
    void AABB::merge(const AABB& box)
    {
        // 计算新的最小点坐标
        _min.x = std::min(_min.x, box._min.x);
        _min.y = std::min(_min.y, box._min.y);
        _min.z = std::min(_min.z, box._min.z);
    
        // 计算新的最大点坐标
        _max.x = std::max(_max.x, box._max.x);
        _max.y = std::max(_max.y, box._max.y);
        _max.z = std::max(_max.z, box._max.z);
    }
    //设置最大顶点与最小顶点
    void AABB::set(const Vec3& min, const Vec3& max)
    {
        this->_min = min;
        this->_max = max;
    }
    //顶点复位 初始化信息
    void AABB::reset()
    {
    	_min.set(99999.0f, 99999.0f, 99999.0f);
    	_max.set(-99999.0f, -99999.0f, -99999.0f);
    }
    //检测坐标信息是否有误
    bool AABB::isEmpty() const
    {
        return _min.x > _max.x || _min.y > _max.y || _min.z > _max.z;
    }
    //由给定点坐标点重新确定最大最小的坐标向量
    void AABB::updateMinMax(const Vec3* point, ssize_t num)
    {
        for (ssize_t i = 0; i < num; i++)
        {
            // 最小x坐标
            if (point[i].x < _min.x)
                _min.x = point[i].x;
            
            // 最小y坐标
            if (point[i].y < _min.y)
                _min.y = point[i].y;
            
            // 最小z坐标
            if (point[i].z < _min.z)
                _min.z = point[i].z;
            
            // 最大x坐标
            if (point[i].x > _max.x)
                _max.x = point[i].x;
            
            // 最大y坐标
            if (point[i].y > _max.y)
                _max.y = point[i].y;
            
            // 最大z坐标
            if (point[i].z > _max.z)
                _max.z = point[i].z;
        }
    }
    //通过给定的变换矩阵对包围盒进行变换
    void AABB::transform(const Mat4& mat)
    {
        Vec3 corners[8]; //保存包围盒八个顶点
        //朝向z轴正方向的面
        //左上顶点坐标
        corners[0].set(_min.x, _max.y, _max.z);
        //左下顶点坐标
        corners[1].set(_min.x, _min.y, _max.z);
        //右下顶点坐标
        corners[2].set(_max.x, _min.y, _max.z);
        //右上顶点坐标
        corners[3].set(_max.x, _max.y, _max.z);
    
        //朝向z轴负方向的面
        //右上顶点坐标
        corners[4].set(_max.x, _max.y, _min.z);
        //右下顶点坐标
        corners[5].set(_max.x, _min.y, _min.z);
        //左下顶点坐标
        corners[6].set(_min.x, _min.y, _min.z);
        //左上顶点坐标
        corners[7].set(_min.x, _max.y, _min.z);
    
      
        //顶点变换
        for (int i = 0; i < 8; i++)
            mat.transformPoint(&corners[i]);
        //复位最大顶点最小顶点
        reset();
        //重新计算最大最小点信息
        updateMinMax(corners, 8);
    }
    
    NS_CC_END
    


        

    4. 总结

            最后,AABB碰撞检测算法虽然计算方法简单,速度快,但是仅适用于精度不搞的游戏中。相对于AABB碰撞检测,还有一种更逼近物体并更为精确的一种算法——OBB碰撞检测。在Cocos2d-x 中同样提供了OBB碰撞检测的相应方法,如图 4-1所示:
           
           
          

    图 4-1 


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


    检测碰撞实例
    本实例涉及到物理引擎中物体之间的检测碰撞,当两个物体接触到两个物体分离过程中,会发生一些事件,我们可以通过注册监听器EventListenerPhysicsContact来响应这些事件。
    首先看一下看HelloWorldScene.h文件,它的代码如下:
    #ifndef __HELLOWORLD_SCENE_H__
    #define __HELLOWORLD_SCENE_H__
    
    
    #include "cocos2d.h"
    USING_NS_CC;
    
    
    class HelloWorld : public cocos2d::Layer
    {
    public:
        static cocos2d::Scene* createScene();
        virtual bool init();  
    	virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
    	virtual void onEnter();
    	virtual void onExit();
        
        CREATE_FUNC(HelloWorld);
    
    
    	void addNewSpriteAtPosition(Vec2 p);
    };
    
    
    #endif // __HELLOWORLD_SCENE_H__


    上述代码声明了onEnter和onExit函数,用来处理层进入和退出回调函数。我们会在onEnter函数注册EventListenerPhysicsContact监听器,以便于响应碰撞检测事件,在onExit函数中注销这些监听器。
    HelloWorldScene.cpp中创建物理世界和指定世界的边界语句是在HelloWorld::createScene()和HelloWorld::init()函数中,这两个函数类似于上一节的HelloPhysicsWorld实例,这里不再解释这些函数代码了。
    HelloWorldScene.cpp中与碰撞检测相关的代码是在onEnter和onExit函数中,代码如下:
    void HelloWorld::onEnter()
    {
    	Layer::onEnter();
    	auto listener = EventListenerPhysicsContact::create();
    	listener->onContactBegin = [](PhysicsContact& contact)							①
    	{
    		auto spriteA = (Sprite*)contact.getShapeA()->getBody()->getNode();				②
    		auto spriteB = (Sprite*)contact.getShapeB()->getBody()->getNode();				③
    		
    		if (spriteA && spriteA->getTag() == 1 
    				&& spriteB && spriteB->getTag() == 1) 								④
    		{
    			spriteA->setColor(Color3B::YELLOW);
    			spriteB->setColor(Color3B::YELLOW);
    		}
    		
    		log("onContactBegin");
    		return true;
    	};	
    
    
    	listener->onContactPreSolve = [] (PhysicsContact& contact, 
    											PhysicsContactPreSolve& solve) {				⑤
    
    
    		log("onContactPreSolve");
    		return true;
    	};
    
    
    	listener->onContactPostSolve = [] (PhysicsContact& contact, 
    										const PhysicsContactPostSolve& solve)				⑥
    
    
    		log("onContactPostSolve");
    	};
    
    
    	listener->onContactSeperate = [](PhysicsContact& contact) {						⑦
    		auto spriteA = (Sprite*)contact.getShapeA()->getBody()->getNode();
    		auto spriteB = (Sprite*)contact.getShapeB()->getBody()->getNode();
    		
    		if (spriteA && spriteA->getTag() == 1 
    				&& spriteB && spriteB->getTag() == 1) 
    		{
    			spriteA->setColor(Color3B::WHITE);
    			spriteB->setColor(Color3B::WHITE);
    		}
    		log("onContactSeperate");
    	};
    
    
    	Director::getInstance()->getEventDispatcher()->
    								addEventListenerWithFixedPriority(listener,1); 					⑧
    
    
    }
    
    
    void HelloWorld::onExit()
    {
    	Layer::onExit();
    	log("HelloWorld onExit");
    	Director::getInstance()->getEventDispatcher()->removeAllEventListeners();				⑨
    }


    上述代码的onEnter()函数是进入场景时候回调的函数,我们可以在这里通过auto listener = EventListenerPhysicsContact::create()语句创建物体碰撞检测事件监听器对象。接下来通过第①、⑥、⑤、⑦行使用Lambda表达式定义了事件处理的匿名函数。
    代码第②和第③行是从接触点中取出互相接触的两个节点对象,它的取值过程有点复杂,首先接触点使用getShapeA()和getShapeB()函数获得物体形状,在通过形状的getBody()函数获得物体,通过物体的getNode()函数获得与形状相关的节点对象。第④行代码是进行判断,判断从接触点取出的节点对象是否存在,并且判断是否tag属性为1。
    上面代码第⑧行addEventListenerWithFixedPriority是指定固定的事件优先级注册监听器,事件优先级决定事件响应的优先级别,值越小优先级越高。
    代码第⑨行是在退出层回调函数onExit()中注销所有的监听事件。
    HelloWorldScene.cpp中还有onTouchBegan和addNewSpriteAtPosition两个函数,它们的代码如下。 
    bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
    {
    	Vec2 location = touch->getLocation();
    	addNewSpriteAtPosition(location);
    	return false;
    }	
    
    
    void HelloWorld::addNewSpriteAtPosition(Vec2 p)
    {    
    	auto sp = Sprite::create("BoxA2.png");
    	sp->setTag(1);
    	auto body = PhysicsBody::createBox(sp->getContentSize());
    	body->setContactTestBitmask(0xFFFFFFFF);								①
    	sp->setPhysicsBody(body);	
    	sp->setPosition(p);
    	this->addChild(sp);
    }


    这两个函数的代码与上一节介绍的实例基本一致,但是需要注意的是我们在第①行添加了body->setContactTestBitmask(0xFFFFFFFF)代码,它的作用是设置物体接触时候能否触发EventListenerPhysicsContact中定义的碰撞检测事件。如果两个物体的接触测试掩码(ContactTestBitmask)执行“逻辑与”运算,如果结果为非零值,表明这两个物体会触发碰撞检测事件。默认值是0x00000000,表示清除所有掩码位,0xFFFFFFFF表示所有掩码位都设置为1。
    假设有三个物体(body1、body2和body3),设置接触测试掩码如下:
    body1->setContactTestBitmask (0x01); //0001
    body2->setContactTestBitmask (0x03); //0011
    body3>setContactTestBitmask (0x02); //0010
    那么body1和body2,以及body2和body3是可以触发EventListenerPhysicsContact的碰撞检测事件的,而body1和body3是不能的。
    另外,除了接触测试掩码(ContactTestBitmask)外,物理引擎中还定义了类别掩码(CategoryBitmask)和碰撞掩码(CollisionBitmask),它们的作用是当两个物体接触时候是否发生“碰撞反应”,“碰撞反应”会表现为一个物体受到另外物体的碰撞,而改变运动方向。由于两个物体是“刚体”,在碰撞的时候两个物体不会交叉。
    那么类别掩码(CategoryBitmask)与碰撞掩码(CollisionBitmask)究竟是什么呢?
    1、类别掩码
    定义了一个物体所属类别,每一个物体在场景中能被分配到多达32个不同的类别。通过body->setCategoryBitmask(int bitmask)函数设置类别掩码。
    2、碰撞掩码
    当两个物体相互接触时,该物体的碰撞掩码与另一个物体的类别掩码执行“逻辑与”运算,如果结果为非零值,该物体能够对另一个物体的碰撞发生反应。通过body->setCollisionBitmask(int bitmask) 函数设置的碰撞掩码。
    综上所述,类别掩码(CategoryBitmask)与碰撞掩码(CollisionBitmask)决定了物体能否发生“碰撞反应”。而接触测试掩码(ContactTestBitmask)的设置,能够检测是否发生接触发生,并且触发EventListenerPhysicsContact监听事件。 接触测试掩码与类别掩码和碰撞掩码没有什么关联。
    假设有三个物体(body1、body2和body3),它们设置如下:
    body1->setCategoryBitmask(0x01);	//0001
    body1->setCollisionBitmask(0x03);	//0011
    
    
    body2->setCategoryBitmask(0x02);	//0010
    body2->setCollisionBitmask(0x01);	//0001
    
    
    body3->setCategoryBitmask(0x04);	//0100
    body3->setCollisionBitmask(0x06);	//0110


    body1和 body1之间、body1和 body2、body3和 body3能够互相发生碰撞反应,body1和body3不能发生碰撞反应。box 2不能对box3的碰撞发生反应,但box 3能够对box2的碰撞发生反应。



    更多内容请关注最新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课堂微信公共平台
    展开全文
  • 1: 理解物体类型和分类,配置碰撞矩阵;2: 编写碰撞响应函数,监听碰撞事件;3: 学会了解Sensor来做触发器,只触发碰撞不改变运动; 物体类型与碰撞矩阵 1: 添加物体类型: Add Layer, 每类型对应一名字group与...
  • 最近在学习cocos creator, 在实现一手指移动物体与其他物体碰撞的场景时,缓慢移动不会出现问题,当快速移动时,碰撞检测不会生效, 使用刚体的bullet也解决不了(这感觉好像是物品自移动场景下使用的,没进行验证),...
  • cocos2dx 碰撞检测 总结

    2016-10-26 18:01:33
    之前所用到的碰撞检测均为cocos提供的方法。 1、点与矩形碰撞 auto rec = tubeOn1->getBoundingbox();// 得要矩形区域 bool collision = rec.containsPoint(p);//p这点是否在矩形区域内,返回一bool型的值 2...
  • 下面是main.lua文件的完整代码,单击屏幕任意一点会创建一精灵,精灵之间相互碰撞后产生回调事件。 local MainScene = class (&amp;amp;amp;amp;quot;MainScene&amp;amp;amp;amp;quot;,function() ...
  • 而且网上好像还真比较难找到答案, 今天翻了一下cocos源码发现Ray 已经封装了intersects函数,那么剩下的工作其实很简单了, 从屏幕的一point 转化为 一条射线, 然后从一3D物体拿到碰撞盒后调用intersects 就...
  • #include "HelloWorldScene.h" #include "cocostudio/CocoStudio.h" #include "ui/CocosGUI.h" USING_NS_CC; using namespace cocostudio::timeline; Scene* HelloWorld::createScene() ... auto scene = Scene::...
  • cocos creator 碰撞检测

    2020-01-08 13:22:19
    creator的碰撞检测系统分为碰撞检测系统和物理碰撞检测系统两模块,并且这两模块是相互独立的(这边主要是非物理碰撞检测系统) 1、在制作碰撞检测系统的时候要对物体进行分组,即指定节点的分组与分组的碰撞...
  • 碰撞检测是物理世界中很重要的一部分,
  • 物理引擎中不规则物体碰撞检测,chipmunk,不规则物体碰撞检测,Cocos2d-x中不规则物体碰撞检测
  • cocos creator 中使用简单的碰撞系统实现物理引擎的效果 最近在写一帧同步的小游戏, 服务器用的pinus, 客户端就是cocos creator了 因为要实现玩家在物理环境的跳跃, 碰撞, 移动, 最开始准备使用cocos creator的...
  • cocos-creater-碰撞系统

    2020-06-15 15:50:20
    有下面三个回调函数,分别会在刚刚发生碰撞,持续碰撞碰撞结束调用: 刚刚发生碰撞 /** * 当碰撞产生的时候调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身...
  • Cocos碰撞系统设计者堪称天才,我只花了两小时就找到了问题所在。 碰撞组件中的Collider并不具备物理特性,意思是两带Collider组件的物体发生碰撞,并不会有任何物理上的反馈,这和刚体没有任何关系,但是,...
  • 如果已经知道了两相互碰撞物体进行碰撞前的 线速度, 角速度, 质心坐标, 被碰撞点的坐标, 碰撞方向, 质量, 转动惯量, 恢复系数, 那么可以用以下公式求得两个物体对对方造成的碰撞冲量大小: J = -vr(e + 1) / ( 1...
1 2 3 4 5 ... 20
收藏数 2,026
精华内容 810
关键字:

3个以上物体碰撞 cocos