從「子彈擊中敵機」到「角色撞牆阻擋」,碰撞偵測是遊戲邏輯的基石。J2ME 平台無浮點運算 (CLDC 1.0) 或浮點效能極差 (CLDC 1.1 早期裝置),演算法必須以整數運算為主,並避免開方、三角函數等昂貴操作。
幾何定義:矩形 1 左上角 (x1, y1)、寬 w1、高 h1;矩形 2 左上角 (x2, y2)、寬 w2、高 h2。
數學條件:兩矩形中心點在 X 軸距離 ≤ 寬度和一半,且 Y 軸距離 ≤ 高度和一半。
| (x1 + w1/2) - (x2 + w2/2) | ≤ (w1 + w2) / 2
| (y1 + h1/2) - (y2 + h2/2) | ≤ (h1 + h2) / 2
整數優化實作 (避免除法與絕對值):
public boolean rectCollide(int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2) {
// 分離軸定理 (SAT) 形式:任一軸投影不重疊即無碰撞
if (x1 + w1 < x2) return false; // rect1 在 rect2 左側
if (x2 + w2 < x1) return false; // rect1 在 rect2 右側
if (y1 + h1 < y2) return false; // rect1 在 rect2 上方
if (y2 + h2 < y1) return false; // rect1 在 rect2 下方
return true; // 所有軸投影重疊 → 碰撞
}
幾何定義:圓 1 中心 (x1, y1)、半徑 r1;圓 2 中心 (x2, y2)、半徑 r2。
數學條件:兩圓心距離 ≤ 半徑和。
√[(x1-x2)² + (y1-y2)²] ≤ r1 + r2
整數優化:雙方同乘平方,消除開方運算:
(x1-x2)² + (y1-y2)² ≤ (r1+r2)²
完整實作:
public boolean circleCollide(int x1, int y1, int r1,
int x2, int y2, int r2) {
int dx = x1 - x2;
int dy = y1 - y2;
int rSum = r1 + r2;
return (dx*dx + dy*dy) <= (rSum * rSum);
}
找出矩形上距離圓心最近的點,再判斷該點是否在圓內:
public boolean rectCircleCollide(int rx, int ry, int rw, int rh,
int cx, int cy, int cr) {
// 最近點座標
int nearestX = Math.max(rx, Math.min(cx, rx + rw));
int nearestY = Math.max(ry, Math.min(cy, ry + rh));
int dx = nearestX - cx;
int dy = nearestY - cy;
return (dx*dx + dy*dy) <= (cr * cr);
}
| 策略 | 原理 | 適用場景 | 效能 |
|---|---|---|---|
| 多圓形近似 | 用數個圓覆蓋不規則物體 | 圓形為主的角色/敵機 | O(n) 圓形檢測 |
| 多矩形近似 | 分解為矩形集合 | 矩形為主的載具/建築 | O(n) 矩形檢測 |
| 凸包/多邊形 | SAT 分離軸定理 | 精確物理模擬 | O(n+m) 頂點數 |
| 像素級遮罩 | 位圖 AND 運算 | 極高精度需求 (彈幕遊戲) | 極慢,僅最終確認用 |
細節檢測前快速剔除明顯不相交物件:
// 矩形重疊
assertTrue(rectCollide(0,0,10,10, 5,5,10,10));
// 矩形相切 (邊界視為碰撞)
assertTrue(rectCollide(0,0,10,10, 10,0,10,10));
// 圓形內含
assertTrue(circleCollide(0,0,10, 0,0,5));
// 圓形外離
assertFalse(circleCollide(0,0,5, 20,0,5));
掌握這些基於整數運算的基礎碰撞算法,是 J2ME 遊戲開發者構建高效物理系統的起點。現代引擎雖封裝了複雜的物理模擬,但核心數學原理始終不變。