前段时间自己开发了一个冒险岛类的游戏,游戏中需要用到上下左右中五个方向的碰撞检测。这里把思路分享给大家
先把一个节点用一个巨型区域标识,锚点为左下角向右和向上为正,记为a ,给他上下左右四个方向设置四个矩形碰撞区域如下图
这样节点就有5个碰撞区域分别为:
this.rectU = {};
this.rectL = {};
this.rectD = {};
this.rectR = {};
this.rectM = {};
初始化局域:
initRect() {
this.rectU['width'] = this.node.width - cc.GameConfig.CONSTANT.OFFSET_X2;
this.rectU['height'] = cc.GameConfig.CONSTANT.COLLISION_RECT_W;
this.rectL['width'] = cc.GameConfig.CONSTANT.COLLISION_RECT_W;
this.rectL['height'] = this.node.height - cc.GameConfig.CONSTANT.OFFSET_Y2;
this.rectD['width'] = this.node.width - cc.GameConfig.CONSTANT.OFFSET_X2;
this.rectD['height'] = cc.GameConfig.CONSTANT.COLLISION_RECT_W;
this.rectR['width'] = cc.GameConfig.CONSTANT.COLLISION_RECT_W;
this.rectR['height'] = this.node.height - cc.GameConfig.CONSTANT.OFFSET_Y2;
this.rectM['width'] = this.node.width;
this.rectM['height'] = this.node.height ;
},
initRectPosition() {
this.rectU['x'] = this.node.x + cc.GameConfig.CONSTANT.OFFSET_X;
this.rectU['y'] = this.node.y + this.node.height;
this.rectL['x'] = this.node.x + this.node.width;
this.rectL['y'] = this.node.y + cc.GameConfig.CONSTANT.OFFSET_Y;
this.rectD['x'] = this.node.x + cc.GameConfig.CONSTANT.OFFSET_X;
this.rectD['y'] = this.node.y - cc.GameConfig.CONSTANT.COLLISION_RECT_W;
this.rectR['x'] = this.node.x - cc.GameConfig.CONSTANT.COLLISION_RECT_W;
this.rectR['y'] = this.node.y + cc.GameConfig.CONSTANT.OFFSET_Y;
this.rectM['x'] = this.node.x ;
this.rectM['y'] = this.node.y ;
},
脚本获取区函数为:
getRect(type) {
this.initRectPosition(); //如果节点位置在变动,需要更新区域位置
switch (type) {
case 0: return this.rectU;
case 1: return this.rectL;
case 2: return this.rectD;
case 3: return this.rectR;
case 4: return this.rectM;
default:
break;
}
},
假设 a节点与b节点进行碰撞检测 a为主 碰撞检测方法为checkCollision,
If(this.checkCollision(scriptA.getRect(4), scriptB.getRect(0))){
scriptA.preDownObj = scriptB.node;
}else if(this.checkCollision(scriptA.getRect(4), scriptB.getRect(1))){
scriptA.preLeftObj = scriptB.node;
} else if(this.checkCollision(scriptA.getRect(4), scriptB.getRect(2))){
scriptA.preUpObj = scriptB.node;
} else if(this.checkCollision(scriptA.getRect(4), scriptB.getRect(3))){
scriptA.preRightObj = scriptB.node;
}
这样就得到了a四个方向即将碰到的节点
在移动的时候,再判断一下,
左右移动代码如下
move() {
if (this.direct) {
if (this.preRightRoad) {
if (this.node.x + this.node.width + this.moveSpeed <= this.preRightRoad.x) {
this.node.x += this.moveSpeed;
} else {
this.direct = false;
}
} else {
this.node.x += this.moveSpeed;
}
} else {
if (this.preLeftRoad) {
if (this.node.x - this.moveSpeed >= this.preLeftRoad.x + this.preLeftRoad.width) {
this.node.x -= this.moveSpeed;
} else {
this.direct = true;
}
} else {
this.node.x -= this.moveSpeed;
}
}
},
上升代码如下
if(this.dropSpeed > 0){
this.dropSpeed -= this.increment;
if (this.preShakeRoad) {
if (this.node.y + this.node.height + this.dropSpeed <= this.preShakeRoad.y) {
this.isJump = false;
this.isDrop = true;
}else{
this.node.y += this.dropSpeed;
}
} else {
this.node.y += this.dropSpeed;
}
}else{
this.dropSpeed = 0;
this.isDrop = true;
this.isJump = false;
}
下落代码如下
if (this.dropSpeed <= this.dropMaxSpeed) {
this.dropSpeed += this.increment;
}
if(this.preStandRoad.){
if (this.node.y - this.dropSpeed >= this.preStandRoad.y + this.preStandRoad.height) {
this.node.y -= this.dropSpeed;
} else {
this.dropSpeed = 0;
this.isDrop = false;
this.standRoad = this.preStandRoad;
}
}
这里的moveSpeed 和dropSpeed 都不要超过cc.GameConfig.CONSTANT.COLLISION_RECT_W,不然会出现穿透的情况
再灵活点,可以给接节点设置五个区域设置5个标志IsCollisionUp, IsCollisionDown, IsCollisionLeft, IsCollisionRight,IsCollisionMiddle,灵活的控制不同的节点要检测哪些方向
游戏中用到的矩形被撞方法
If(a.x + a.width>= b.x && a.x <= b.x + b.width && a.y + a.height >= b.y && a.y <= b.y + b.height){
Return true;
}
最后打个小广告,低价出售一套类似pc冒险岛的代码(单机),可以自己设计编辑关卡,新增元素,用来学习或做小游戏上线均可(需要自己设计关卡)微信上性能表现良好(比较流畅),其他平台更没问题流畅得飞起(比如oppo ,qq),需要的朋友加qq2411537247私聊,具体效果可参考这个游戏 , 微信扫码玩