一、矩形碰撞
1. 使用rectangle的intersects判斷碰撞
let rectA:egret.Rectangle = this.red.getBounds();
let rectB:egret.Rectangle = this.blue.getBounds();
//獲得的rect不包含x,y位置
console.log(rectA); //x=0,y=0,width=200,height=200
console.log(rectB); //x=0,y=0,width=200,height=200
//必須加上方塊所在的x,y
rectA.x += this.red.x;
rectA.y += this.red.y;
rectB.x += this.blue.x;
rectB.y += this.blue.y;
let startTime = egret.getTimer();
for(let i=0;i<1000;i++){
if(rectA.intersects(rectB)){
console.log("hit");
}else{
console.log("no hit");
}
}
console.log(egret.getTimer() - startTime); //檢測1000次,耗時215ms
下圖:no hit

下圖:hit

矩形旋轉后,還能正確判斷碰撞嗎?
下圖:no hit

下圖:no hit

下圖:hit

矩形旋轉后,並不能正確的判斷碰撞了。查看源代碼,可知並沒有計算rotation這樣的算法。
/**
* 確定在 toIntersect 參數中指定的對象是否與此 Rectangle 對象相交。此方法檢查指定的 Rectangle
* 對象的 x、y、width 和 height 屬性,以查看它是否與此 Rectangle 對象相交。
* @param toIntersect 要與此 Rectangle 對象比較的 Rectangle 對象。
* @returns 如果兩個矩形相交,返回true,否則返回false
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public intersects(toIntersect:Rectangle):boolean {
return Math.max(this.x, toIntersect.x) <= Math.min(this.right, toIntersect.right)
&& Math.max(this.y, toIntersect.y) <= Math.min(this.bottom, toIntersect.bottom);
}
所以intersects的碰撞檢測適用:
1. 用於矩形(未旋轉)
2. eui對象(才有right、bottom屬性)
3. 修改了錨點也能正常檢測
2. 自定義的矩形碰撞檢測
protected childrenCreated(){
let startTime = egret.getTimer();
for(let i=0;i<1000;i++){
if(this.checkRect(this.red, this.blue)){
console.log("hit");
}else{
console.log("no hit");
}
}
console.log(egret.getTimer() - startTime); //檢測1000次,耗時220ms
}
/**
* 檢測碰撞矩形
* @objA 對象A
* @objB 對象B
*/
public checkRect(objA: egret.DisplayObject,objB: egret.DisplayObject) {
var x1 = objA.x - objA.anchorOffsetX;
var y1 = objA.y - objA.anchorOffsetY;
var x2 = objB.x - objB.anchorOffsetX;
var y2 = objB.y - objB.anchorOffsetY;
if(y1 > (y2 - objA.height) && y1 < (y2 + objB.height)) {
if(x1 > (x2 - objA.width) && x1 < (x2 + objB.width)) {
return true;
}
}
return false;
}
適用范圍:
1. 只要是矩形顯示對象就可以,對比intersects不要求必須是eui對象
2. 對於旋轉對象,同樣沒法碰撞檢測
3. 對象修改了錨點也能正確檢測
3. 旋轉后的圖形,也能正確碰撞。比如坦克大戰中,坦克和牆等地形的碰撞檢測方法

給坦克周圍增加碰撞點

然后用hitTestPoint方法去檢測碰撞點和矩形的碰撞。
這種方法,在主對象旋轉后,依附於這個對象的紅點的位置是會隨着旋轉變化的,這樣可以判斷旋轉對象的碰撞了。
注意:使用hitTestPoint時,將紅點的坐標使用localToGlobal或者其他方式轉成和需要碰撞檢測的物體同一坐標系。

物體objA,objA上有多個碰撞點,hitPointList就是碰撞點列表,上圖中的坦克紅點。
物體objB,需要檢測的和坦克碰撞的矩形,rect是objB的矩形框
//碰撞檢測
let rect = new egret.Rectangle(objB.x - objB.anchorOffsetX, objB.y -
objB.anchorOffsetY, objB.width, objB.height);
let hitPointList = objA.hitPointList;
let len = hitPointList.length;
let p:egret.Point = new egret.Point();
//遍歷碰撞點和矩形碰撞
for(let i=0;i<len;i++){
p = objA.localToGlobal(hitPointList[i].x, hitPointList[i].y);
if(rect.containsPoint(p)){
console.log("hit");
break;
}
}
二、圓形碰撞
protected childrenCreated(){
let startTime = egret.getTimer();
for(let i=0;i<1000;i++){
if(this.checkCircle(this.red, this.blue, 100)){
console.log("hit");
}else{
console.log("no hit");
}
}
console.log(egret.getTimer() - startTime); //檢測1000次,耗時250ms
}
/**
* 根據圓形的半徑,檢查圓形是否碰撞
* @ballA 圓形A
* @ballB 圓形B
* @radius 半徑
* @return 是否碰撞
*/
public checkCircle(circleA:egret.DisplayObject, circleB:egret.DisplayObject, radius:number){
var pA:egret.Point = new egret.Point(circleA.x, circleA.y);
var pB:egret.Point = new egret.Point(circleB.x, circleB.y);
if(egret.Point.distance(pA, pB) <= radius*2){
return true;
}
return false;
}
下圖:no hit

下圖:hit

適用:
1. 圓形碰撞
2. 錨點需另行計算
3. 錨點在中心的話,旋轉后也能正常碰撞檢測。
三、點碰撞檢測
protected childrenCreated(){
//不加這個,無法檢測
this.validateNow();
let startTime = egret.getTimer();
for(let i=0;i<1000;i++){
if(this.red.hitTestPoint(this.blue.x, this.blue.y, false)){
console.log("hit");
}else{
console.log("no hit");
}
}
console.log(egret.getTimer() - startTime); //檢測1000次,耗時260ms
}
因為hitTestPoint第三個參數false,所以不是檢測像素,而是檢測邊框碰撞。所以藍點沒碰到圓,但是在圓的矩形框內,也算是hit。
下圖:hit

下圖:藍色點在紅色圓的矩形框范圍內

hitTestPoint第三個參數為true,檢測像素。非常耗時。檢測1000次,耗時2100ms。
下圖:no hit

下圖:hit 檢測1000次,耗時4000ms

四、兩個不規則圖形碰撞
五、不規則圖形和規則圖形碰撞檢測
