cocos creator 不用物理系统,自己检测碰撞遇到的坑

本文介绍了在Cocos Creator中避免使用物理系统进行碰撞检测,而是采用自定义方法处理角色碰撞后的回弹。作者分享了在理解AABB碰撞框属性时遇到的困惑,特别是aabb.x, aabb.y与center的区别。通过示例代码展示了如何计算碰撞并实现回弹效果,以应对不同朝向的角色碰撞场景。" 52490193,1347733, Realm数据库深度解析与实战,"['Android开发', '数据库', 'ORM框架', ' Realm', '移动数据库']

这是官方给的碰撞出发回调 ,other和self分别代表碰撞的对方node,和我的node 

node中包含了world.aabb,是碰撞框,方便计算用的,里边有一些属性

onCollisionStay(other, self) {

        //console.log('on collision enter');

        // 碰撞系统会计算出碰撞组件在世界坐标系下的相关的值,并放到 world 这个属性里面

        var world = self.world;

        // 碰撞组件的 aabb 碰撞框

        var aabb = world.aabb;

        // 节点碰撞前上一帧 aabb 碰撞框的位置

        var preAabb = world.preAabb;

        // 碰撞框的世界矩阵

        var t = world.transform;

        // console.log("------世界碰撞区域-----", t, aabb.x, aabb.y, aabb.width, aabb.height);

        // 以下属性为圆形碰撞组件特有属性

        var r = world.radius;

        var p = world.position;

}

作为以前写unity的我来说,一直认为 aabb中的x,y是碰撞框的中心点,导致计算碰撞错误

至于x,y具体表示碰撞框什么情况下的位置,我也不得而知了

下面这个如图是aabb中的数据,-112,870是aabb.center中的坐标,也就是碰撞框的中心点,

下面的x:-161,y:829是aabb.x  aabb.y的位置

这两个位置是差别还是有不少呢

这个导致我计算是否碰撞一直出错

一开始是用中心点加宽的一半,计算出最大x,其实这里aabb.xMax就是最大x

还有xMinx,xMiny等等都是提供好的

写这篇的目的主要是要记住这次教训

至于为什么aabb中的x,y和center不一样,希望有知道的朋友可以在下方解释一下,谢谢啦

最后贴上我自己计算角色碰撞后回弹的代码

            let otherR = other.world.aabb.xMax;// 碰撞物的右边x

            let otherL = other.world.aabb.xMin;// 碰撞物的左边x

            let otherU = other.world.aabb.yMax;// 碰撞物的上边x

            let otherD = other.world.aabb.yMin;// 碰撞物的下边x

            let myR = self.world.aabb.xMax;// 我的右边x

            let myL = self.world.aabb.xMin// 我的左边x

            let myU = self.world.aabb.yMax;// 我上边x

            let myD = self.world.aabb.yMin;// 我的下边x

            if(this.lookAt===GameConfig.RoleDirection.left|| this.lookAt === GameConfig.RoleDirection.right)

            {// 角色当前朝向是左或者右

                if((myR-otherL>=0&&myR-otherL<60)||(otherR-myL>=0&&otherR-myL<60))

                {// 我的最大x大于他的最小x,右侧撞到// 他的最大x大于我的最小x,左侧撞到

                    dir = this.lookAt; // 记录撞到的方向

                }

                // 没有找到方向

                if(dir===GameConfig.RoleDirection.none)

                {

                   // 还要看看上下方向有没有撞到

                    if(myU-otherD>=0&&myU-otherD<60)

                    {// 我的最大y大于他的最小y,上侧撞到

                        dir = GameConfig.RoleDirection.up;

                    }

                    if(otherU-myD>=0&&otherU-myD<60)

                    {// 他的最大y大于我的最小y,下侧撞到

                        dir = GameConfig.RoleDirection.down;

                    }

                }

            }

            if(this.lookAt===GameConfig.RoleDirection.up|| this.lookAt === GameConfig.RoleDirection.down)

            {// 角色当前朝向是上或者下

                if((myU-otherD>=0&&myU-otherD<60)||(otherU-myD>=0&&otherU-myD<60))

                {// 我的最大y大于他的最小y,上侧撞到//他的最大y大于我的最小y,下侧撞到

                    dir = this.lookAt;

                }

                

                if(dir===GameConfig.RoleDirection.none)

                {// 左右方向没有撞到

                    // 还要看看左右方向有没有撞到

                    if(myR-otherL>=0&&myR-otherL<60)

                    {// 我的最大x大于他的最小x,右侧撞到

                        dir = GameConfig.RoleDirection.right;

                    }

                    if(otherR-myL>=0&&otherR-myL<60)

                    {// 他的最大x大于我的最小x,左侧撞到

                        dir = GameConfig.RoleDirection.left;

                    }

                }

            }

                先根据角色当前朝向,确定是不是当前方向撞了,如果不是当前方向,再判断另外两个方向是不是撞到了,这样记录dir是撞到的方向

然后得到与dir相反的方向,让角色往dir反方向回弹一下,这里的代码是碰撞的回调,只要有接触碰撞,就回弹一下,直到没有接触

这里是因为帧同步不能用物理系统自己检测碰撞,不同机型会产生误差,所以需要自己根据碰撞器计算是否撞到了,但是这个回弹效果也没有办法,因为是撞到后

才能判断,不能让角色擦其他障碍物走,所以肯定要回弹一下,回弹后再让角色继续走,撞到的时候记录这个方向是不能走的,可能另外两个方向也擦着边,可能只有反方向可以走

回弹期间不可以走

CocosCreator实现的 解救人质 游戏,学会碰撞检测rescue.7z // Bullet.js cc.Class({ extends: cc.Component, properties: { mSpeed: 300, }, // LIFE-CYCLE CALLBACKS: // onLoad () {}, start() { var manager = cc.director.getCollisionManager(); // 获取碰撞检测系统 manager.enabled = true; }, update(dt) { // 设置子弹移动,当超出屏幕范围未发生碰撞时自动销毁 this.node.y += this.mSpeed * dt; if (this.node.y > 580) { console.log('超出屏幕范围,子弹销毁!'); this.node.destroy(); } }, /** * 当碰撞产生的时候调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionEnter: function (other, self) { console.log('on collision enter'); if (other.tag == 1) { // 子弹碰到人质时,解救失败! console.log('解救人质失败!'); var failLabel = this.node.parent.getChildByName('failLabel'); failLabel.active = true; this.node.destroy(); } else if (other.tag == 2) { // 子弹碰到敌人时,解救成功! console.log('解救人质成功!'); var successLabel = this.node.parent.getChildByName('successLabel'); successLabel.active = true; this.node.destroy(); } }, /** * 当碰撞产生后,碰撞结束前的情况下,每次计算碰撞结果后调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionStay: function (other, self) { console.log('on collision stay'); }, /** * 当碰撞结束后调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionExit: function (other, self) { console.log('on collision exit'); } });
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值