碰撞就是游戲中的元素是否碰到一起,比如打飛機游戲,沒躲避炮彈就算碰撞,要檢測出來,要game over的。主要講講2D游戲里的碰撞檢測,傳統的2D游戲可以把不同元素當作基本圖形粗糙地來檢測碰撞與否?
1、矩形判斷
比如把游戲中敵我雙方人物都當作矩形來檢測兩個矩形是否相交。那么如何判讀兩個矩形是否相交呢?
相交 == !(不相交),不相交較好判斷,優先判讀不相交再取反就可以了。
如上圖旁邊矩形都不和中間矩形相交,它們都有共同特點:
1、旁邊矩形(B)的xy坐標沒有同時介於中間矩形(A)x~x',y~y'間,即沒有一個點出現在A矩形內部,用偽代碼判斷不相交就是
B.max(x) < A.min(x) || B.min(x) > A.max(x) || B.max(y) < A.min(y) || B.min(y) > A.max(y)
那么判讀相交的偽代碼就是
!(B.max(x) < A.min(x) || B.min(x) > A.max(x) || B.max(y) < A.min(y) || B.min(y) > A.max(y))
2、當然由於矩形的特殊性,當知道矩形左上角的坐標和寬高時就可以知道其他三點的坐標,而且左上角坐標一般也是我們繪制矩形要傳遞的參數。
設兩個矩形(A,B)坐標寬高為x1,y1,w1,h1和x2,y2,w2,h2,判斷不相交代碼就是:
1 /** 2 * 判斷兩矩形是否相交 3 */ 4 public boolean isCollsionWithRect(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { 5 // 矩形A位於矩形B的右側 6 if (x1 >= x2 && x1 >= x2 + w2) { 7 return false; 8 // 矩形A位於矩形B的左側 9 } else if (x1 <= x2 && x1 + w1 <= x2) { 10 return false; 11 // 矩形A位於矩形B的下側 12 } else if (y1 >= y2 && y1 >= y2 + h2) { 13 return false; 14 // 矩形A位於矩形B的上側 15 } else if (y1 <= y2 && y1 + h1 <= y2) { 16 return false; 17 } 18 // 不相交都不滿足,那就是相交了 19 return true; 20 }
2、圓形判斷
圓形判讀比較簡單,即判斷兩個圓心距離是否大於兩個圓的半徑之和
1 /** 2 * 圓形碰撞 3 * @param x1 圓形1的圓心X坐標 4 * @param y1 圓形2的圓心X坐標 5 * @param x2 圓形1的圓心Y坐標 6 * @param y2 圓形2的圓心Y坐標 7 * @param r1 圓形1的半徑 8 * @param r2 圓形2的半徑 9 * @return 10 */ 11 private boolean isCollisionWithCircle(int x1, int y1, int x2, int y2, int r1, int r2) { 12 //Math.sqrt:開平方 13 //Math.pow(double x, double y): X的Y次方 14 if (Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) <= r1 + r2) { 15 //如果兩圓的圓心距小於或等於兩圓半徑則認為發生碰撞 16 return true; 17 } 18 return false; 19 }
3、多矩形判斷
這時我們就要封裝多個矩形來一一判斷是否有碰撞。
1 //Rect 類中的四個屬性 top bottom left right 2 //分別表示這個矩形的 上 下 左 右 3 public boolean isCollsionWithRect(Rect[] rectArray, Rect[] rect2Array) { 4 Rect rect = null; 5 Rect rect2 = null; 6 for (int i = 0; i < rectArray.length; i++) { 7 //依次取出第一個矩形數組的每個矩形實例 8 rect = rectArray[i]; 9 //獲取到第一個矩形數組中每個矩形元素的屬性值 10 int x1 = rect.left + this.rectX1; 11 int y1 = rect.top + this.rectY1; 12 int w1 = rect.right - rect.left; 13 int h1 = rect.bottom - rect.top; 14 for (int j = 0; j < rect2Array.length; j++) { 15 //依次取出第二個矩形數組的每個矩形實例 16 rect2 = rect2Array[j]; 17 //獲取到第二個矩形數組中每個矩形元素的屬性值 18 int x2 = rect2.left + this.rectX2; 19 int y2 = rect2.top + this.rectY2; 20 int w2 = rect2.right - rect2.left; 21 int h2 = rect2.bottom - rect2.top; 22 //進行循環遍歷兩個矩形碰撞數組所有元素之間的位置關系 23 if (x1 >= x2 && x1 >= x2 + w2) { 24 } else if (x1 <= x2 && x1 + w1 <= x2) { 25 } else if (y1 >= y2 && y1 >= y2 + h2) { 26 } else if (y1 <= y2 && y1 + h1 <= y2) { 27 } else { 28 //只要有一個碰撞矩形數組與另一碰撞矩形數組發生碰撞則認為碰撞 29 return true; 30 } 31 } 32 } 33 return false; 34 }