java 實現精確碰撞檢測。
cnmm22 原創。
用我的方法,你可以在java 裡實現精確的斜角矩形,平行四邊形,不規則矩形,不規則多邊形與圓形的碰撞檢測。
我們知道,在java 裡有一個類,x.getRect().intersects(x1.getRect() 可以實現規則矩形的碰撞檢測:
這是無法容忍的“碰撞檢測”。這不是我要的遊戲效果。
在使我的方法後:
cnmm22 原創,轉載請隨意。
實現方法:我們必須把所有的碰撞分為兩類:與圓形和與多邊形。
圓形與圓形解決方案:檢測兩個碰撞物件的圓心距離,跟兩者半徑之和做比較。
我把要使用的方法都封裝好了,以便您直接使用 :
/** 步驟一、檢測兩個圓心距離 */
public static double getDistance(Point p, double ox, double oy) {
double _x = Math.abs(ox - p.x);
double _y = Math.abs(oy - p.y);
return Math.sqrt(_x * _x + _y * _y);
}
每一張圓形的透明 png圓形圖片,我們都有一個尺寸大小,我們按尺寸大小,得到其半徑。
而要碰撞的兩個圓心座標我們是很好得到的,這個相信我不須解釋。
/* 步驟二、檢測兩個圓心距離,與兩者半徑之和做比較,範例程式碼:
.
Point p1 = new Point(x + W / 2, y + H / 2);
if (Unit.getDistance(p1, w.yx, w.yy) < w.yr) {
.
以上就完成了圓形的碰撞檢測。
多邊形:騷複雜點,。
解決方案:1、描邊,2,檢測邊到點距離。
例如這個圖形:
先描出4個定點,這樣,能以這4個點組合成4條線段。在分別檢測每一條線段與物件中心的距離即可。
示例程式碼:
……………………….
img = tk.getImage(Wall.class.getClassLoader().getResource ("images/4/k8.png"));
rx1 = 1;
rx2 = 14784;
w = 168;
h = 88;
rx3 = 2;
x3 = x;
y3 = y + 5;
w3 = w - 15;
h3 = h - 5;
px11 = x + 14;
px12 = y + 35;
px21 = x + 136;
px22 = y + 7;
px31 = x + 4;
px32 = y + 85;
px41 = x + 149;
px42 = y + 53;
……………………….
px11,px12,是它的第一個點,px21,px22,是它的第二個點,以此類推。x,y是這張向量圖最左上角滴點,不管那個點有沒有畫素,或者是透明,它都是 x, y。這樣通過影象工具,我們很容易得到一組 px1-pxn, px12-pxn2。
示例程式碼:(分別檢測每一條線段與物件中心的距離)
if (Unit.pointToLine(w.px11, w.px12, w.px21, w.px22, x + W / 2, y + H / 2) < 24) {
stay();
return true;
}
if (Unit.pointToLine(w.px11, w.px12, w.px31, w.px32, x + W / 2, y + H / 2) < 24) {
stay();
return true;
}
if (Unit.pointToLine(w.px31, w.px32, w.px41, w.px42, x + W / 2, y + H / 2) < 24) {
stay();
return true;
}
if (Unit.pointToLine(w.px21, w.px22, w.px41, w.px42, x + W / 2, y + H / 2) < 24) {
stay();
return true;
其中 x + W / 2, y + H / 2 ,是點座標,24是檢測距離。以上只是範例。
/** 封裝方法:檢測邊到點距離 */
static double pointToLine(int x1, int y1, int x2, int y2, int x0, int y0) {
double space = 0;
double a, b, c;
a = lineSpace(x1, y1, x2, y2);// 線段的長度
b = lineSpace(x1, y1, x0, y0);// (x1,y1)到點的距離
c = lineSpace(x2, y2, x0, y0);// (x2,y2)到點的距離
if (c <= 0.000001 || b <= 0.000001) {
space = 0;
return space;
}
if (a <= 0.000001) {
space = b;
return space;
}
if (c * c >= a * a + b * b) {
space = b;
return space;
}
if (b * b >= a * a + c * c) {
space = c;
return space;
}
double p = (a + b + c) / 2;// 半周長
double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));// 海倫公式求面積
space = 2 * s / a;// 返回點到線的距離(利用三角形面積公式求高)
return space;
}
無論如何,解決多邊形碰撞檢測,描邊將會是一個相當大工作量的工作,但是一旦使用熟練後,其實也是相當簡便。因為有圖形工具。
這樣就很迅速得到了 px11,px12,px21,px22 ;px31,px32,px41,px42 類似。
以上就完成了不規則矩形的碰撞檢測。
那多邊形怎樣檢測?
多邊形方法類似,多描幾條邊出來,再分辨判斷點到線距離即可。我就不在贅述了。
假設要檢測的物件是一個橢圓又怎嗎辦?
你可以參考這樣的方法:
記住,你描的邊越多,精確度越高,工作量越大。
使用我的方法,你可以最大限度提高碰撞檢測的精確程度,並且可以避免畫素級碰撞檢測帶來的巨大效能損耗,若碰撞的物件為多邊形與多邊形碰撞,或多邊形與曲線碰撞,無法使用我的方法檢測,而實際中,這種碰撞很少,這種情況下,可以建立畫素矩陣,一般的做法比如一個200*200畫素的圖片,我們則需要做一個[200]*[200]的陣列,進行約40000次的遍歷,來完成1幀裡滴碰撞檢測,還要考慮到透明度的計算,其效能消耗相當可觀。