在討論多邊形碰撞檢測之前,我們可以先思考一下遊戲物件怎麼判斷2d圖形有碰撞,靠的是判斷2d圖形在遊戲世界中有接觸,或者有重疊區域,大到包含,小到重疊接觸乙個點。 那麼我們就需要精確計算2d圖形在某一幀有重疊部分,或者預判到下一幀有重疊部分,那麼就是碰撞到了。
先從簡單的模型來討論碰撞。
判斷乙個點是否在多邊形區域內,我們可以先從簡單的模式來。
判斷乙個點是否在矩形區域內,假設這個矩形平行於xy軸,那麼我們可以通過,點的座標與矩形四點的座標進行比較 點(x,y),矩形四點 a(x1,y1)、b(x2,y2)、c(x3,y3)、d(x4,y4) abcd四點自左下角,順時針排列。x1=x4 , x2=x3 , y1=y2 , y3=y4
若 x1 < x < x2,且 y1 < y < y3 那麼點在矩形範圍內。
拓展下去,如果矩形進行了旋轉,不再平行於xy軸,又應當怎麼判斷呢?
提乙個不恰當的方案: 可以將點與矩形四點連線,可以形成至少三個至多四個三角形。當點在矩形線上時,形成三個三角形。 將形成的三角形面積累加,如果面積和等於矩形面積,那麼點在矩形內,如果面積和大於矩形面積,那麼就不在矩形內。
不過這種計算方式肯定不適合計算多邊形,所以不適用於多邊形碰撞。
射線法不僅僅適用於規則的矩形,也適用於多邊形。
沿著點做多條射線,那麼每條射線就會與多邊形產生n個交點(0個交點也算)。若某一條射線產生奇數個交點,那麼就認定點在多邊形範圍內。
按照簡單的圖形開始
圓形與圓形是最簡單的判斷了,只需要判斷半徑和與圓心距離的關係就能得到碰撞結果。
(r1+r2)^2 <= (x1-x2)^2 + (y1-y2)^2
求出矩形上距離圓心上的最近點p
如圖所示:
delevin:【opengl】簡單2d碰撞遊戲zhuanlan.zhihu.com
凸多邊形是指在多邊形中任意取兩點,將兩點連線,產生一條線段,如果線段完整的處在多邊形內,那麼就是凸多邊形,如果線段有部分處於多邊形外,就屬於凹多邊形。 這裡先討論凸多邊形。
凸多邊形的碰撞判斷方式是分離軸定理。 指的是將乙個凸n邊形取每條邊的法向量,可以得到n條法向量,那麼兩個凸n邊形就能得到2n條法向量,我們將兩個圖形投影到每條法向量上,在每條法向量上將得到兩條線段,如果沒條法向量上的線段都有重合部分,那麼就認定凸多邊形相互碰撞了。反之,則沒有碰撞。
其實就是把凹多邊形進行分割,拆成凸多邊形,然後進行碰撞判斷。
要知道遊戲內的物件數量可能非常多,那麼每一幀需要進行碰撞檢測的遊戲數量將讓cpu不堪重負,因此,需要採取必要的手段,減少碰撞計算。前面提到的都是計算方式,這裡將講解一些減少計算的手段。
我們將遊戲物件按座標劃分區域,如果有必要,可以將四叉樹的深度增加,將遊戲物件劃分區域分的更細。 如下所以:
劃分區域後,我們可以只對區域內的節點進行檢測碰撞,因為在邏輯上我們就可以判斷到,不在乙個區域內的兩個節點不沒有碰撞的,也就沒有計算碰撞的必要了。為此,我們需要每一幀去更新這個四叉樹,這就是在用空間換時間,犧牲部分空間來儲存四叉樹,保證計算量的減少。
delevin:【opengl】基於四叉樹的2d碰撞檢測zhuanlan.zhihu.com
要知道多邊形是有可能特別複雜的,如果區域內每個多邊形的邊數都特別大,那麼意味著每兩個多邊形進行計算的消耗時間將特別高,這個時候我們需要將多邊形進行矩形包裹。 因為矩形是相對簡單,方便計算的2d圖形。 有了包圍盒,我們就可以在進行分離軸定理計算前,先進行一步矩形與矩形的計算。(當然這裡並不一定要選擇矩形進行包圍,也可以是圓形,這個視情況而定,這裡直接討論矩形情況)
步驟如下:
矩形包圍盒判斷碰撞,如果有碰撞,再進行第二步,如果無碰撞,就認定為無碰撞,不用進行第二步。
分離軸定理計算多邊形碰撞,如果有碰撞,則有碰撞,如果無,則無碰撞。
lua實現cocos多邊形碰撞檢測
定義幾個資料型別和函式 function vec x,y return endv vec shortcut function dot v1,v2 return v1 1 v2 1 v1 2 v2 2 endfunction normalize v local mag math.sqrt v 1 2 ...
碰撞檢測 判斷點是否在多邊形內部
本文demo演示 基本判斷原理 判斷乙個點是否在乙個多邊形中,有乙個簡單的做法 從這個點發射一條射線,統計射線與多邊形 有多少條邊相交,奇數表示點在多邊形內,偶數表示點不在多邊形內。為了簡化計算,射線是水平的。如下圖所示 點 a 水平向右的射線有 5 個交點,奇數,a在多邊形內。點 b 水平向右的射...
多邊形與多邊形 位置關係的判斷
c 判斷點的位置方法一 public intisleft point p0,point p1,point p2 private boolpointinfences point pnt1,point fencepnts else if wn 0 return false else return tru...