前言
不久之前在論壇上有人發貼,使用java編寫的超級馬里奧如何實現碰撞檢測,筆者自己以前
也做過Tank大戰。里面同樣涉及到碰撞檢測,翻翻U盤里的東西還在,什么時候也給共享出來。
這篇文章就簡單游戲中的碰撞檢測做一個簡單的總結。首先需聲明的是這里只是2D的碰撞檢測。
碰撞檢測
對于形狀之間如何來判斷是否是碰撞的這要根據具體的形狀來定。在新手練手的小游戲中,
物體形狀一般可以設定為矩形區域,這類規則圖形。它的碰撞檢測可以通過java API中的
Rectangle類來實現碰撞的檢測。
規則圖形碰撞檢測(Rectangle)
首先我們查看API關于Rectangle類的介紹:它就是指定坐標空間的一個區域,這個區域是通過
指定左上角x、y坐標和去高度和寬度來確定的。
接下來看起具體的方法public Rectangle intersection(Rectangle r),這個方法就是碰撞檢測的
關鍵了,如果兩個Rectangle對象有交集,那么他們就有碰撞了。而每個形狀我們都可以得到他們
的Rectangle對象,這樣圖形的碰撞檢測也就得以實現了。
看下具體實現源碼:
[java] view plaincopyprint?
/* 判斷子彈是否擊中障礙物 */
public boolean isHit(com.Alex.map.Map map) {
boolean flag = true;// 代表沒有撞到
// 分類別的得到所有的障礙物
List stuffList = new Vector();
stuffList.addAll(map.getBricks());
stuffList.addAll(map.getIrons());
stuffList.addAll(map.getWaters());
for (int i = 0; i < stuffList.size(); i++) {
Stuff a = stuffList.get(i);
Rectangle tankRectangle = new Rectangle(bullet2.getRec());
Rectangle stuffRectangle = new Rectangle(a.getX(), a.getY(), 20, 20);
if (stuffRectangle.intersects(tankRectangle)) {
flag = false;// 撞到了
break;
}
}
return flag;
}
/* 判斷子彈是否擊中障礙物 */
public boolean isHit(com.Alex.map.Map map) {
boolean flag = true;// 代表沒有撞到
// 分類別的得到所有的障礙物
List stuffList = new Vector();
stuffList.addAll(map.getBricks());
stuffList.addAll(map.getIrons());
stuffList.addAll(map.getWaters());
for (int i = 0; i < stuffList.size(); i++) {
Stuff a = stuffList.get(i);
Rectangle tankRectangle = new Rectangle(bullet2.getRec());
Rectangle stuffRectangle = new Rectangle(a.getX(), a.getY(), 20, 20);
if (stuffRectangle.intersects(tankRectangle)) {
flag = false;// 撞到了
break;
}
}
return flag;
}
上述這個例子就是判斷Tank發出的子彈是否對地圖中的障礙物有碰撞,如果有的話
就做相關的操作(子彈爆炸、障礙物消失)。上述代碼中子彈對象有一個getRec()方法就是
得到子彈圖形的Rectangle對象,具體實現就是根據其坐標和width、height來生成的。
采用此種方法進行碰撞檢測需要注意,對于圖片的實現處理應該盡量的去掉圖標邊角
的空白,不然實際效果可以產生肉眼可辨的誤差。也就是說Rectangle盡量的包住圖形
且Rectangle的區域盡量小。這種碰撞檢測的方法被稱之為多矩形碰撞。
一旦有一個矩形數組中的矩形與另外一個矩形數組的矩形發生碰撞就可認為發生了
多矩形碰撞。其中多圓形碰撞也是同樣的道理,只是包裹的圖形區域是圓形罷了。
不過仔細思考多矩形碰撞同樣會有誤差,雖然這種誤差十分小。
像素級別的碰撞檢測
像素級別的碰撞檢測算得上是最精確的碰撞檢測方法了。
首先遍歷算出一張位圖所有的像素點坐標,然后與另外一張位圖上的所有點坐標進行對比,
一旦有一個像素點的坐標相同,就立刻取出這兩個坐標相同的像素點,通過位運算取出這兩個
像素點的最高位(透明度)進行對比,如果兩個像素點都是非透明像素則判定這兩張位圖發生
碰撞。
介紹了像素碰撞之后可以得到兩個結論:
1、像素碰撞很精確,不論位圖之間是否帶有透明像素,都可以精確判斷;
2、正是因為像素碰撞的這種高精確判定,從而也會造成代碼效率明顯降低!
假設兩張100×100 大小的位圖利用像素級檢測碰撞,僅是遍歷兩張位圖的像素點就要循環
100×100×2=20000 句邏輯代碼;況且還要對篩選出來的相同坐標的像素點進行遍歷對比其
透明值!這種效率可想而知!
當然,這里的像素碰撞只是大致提供一種思路,肯定還可以進行代碼優化;但是不論再優的
代碼,使用像素級進行碰撞檢測終會導致整個程序的運行效率大大降低。因此像素級別的碰
撞檢測在游戲開發中是盡量避免使用的!
規則圖形碰撞檢測2
原文轉自:http://www.anti-gravitydesign.com