<3>2-d邊界碰撞檢測
一、使用向量進行障礙檢測的原理
在遊戲中進行障礙碰撞檢測,基本思路是這樣的:給定乙個障礙範圍,判斷物體在這次移動後會不會進入這個範圍,如果會,就發生碰撞,否則不發生碰撞。在實際操作中,是用物體的邊界來判斷還是其他部位判斷完全取決於程式設計者。這時候,就可以從這個部位沿著速度的方向引出一條速度向量線,判斷一下這條線段(從檢測部位到速度向量終點)和障礙邊界線有沒有交點,如果有,這個交點就是碰撞點。
上面物體a,在通過速度向量移動之後將到達b位置。但是,這次移動將不會順利進行,因為我們發現,碰撞發生了。碰撞點就在那個紅色區域中,也就是速度向量和邊界線的交點。 我們接下來的工作就是要計算這個交點,這是乙個解線性方程組的過程,那麼我們將要用到一樣工具...
二、乙個解線性方程組的有力工具---克蘭姆(cramer)法則
首先要說明一下的是,這個法則是有侷限性的,它必須在乙個線性方程組的係數行列式非零的時候才能夠使用。別緊張,我會好好談談它們的。首先讓我來敘述一下這個法則(我會試著讓你感覺到這不是一堂數學課):
如果線性方程組:
a11*x1 + a12*x2 + ... + a1n*xn = b1
a21*x1 + a22*x2 + ... + a2n*xn = b2
...................................
an1*x1 + an2*x2 + ... + ann*xn = bn
的係數矩陣 a =
__ __
| a11 a12 ... a1n |
| a21 a22 ... a2n |
| ....................... |
| an1 an2 ... ann |
-- --
的行列式 |a| != 0
線性方程組有解,且解是唯一的,並且解可以表示為:
x1 = d1/d , x2 = d2/d , ... , xn = dn/d (這就是/a/=d為什麼不能為零的原因)
這裡d就是行列式/a/的值,dn(n=1,2,3...)是用線性方程組的常數項b1,b2,...,bn替換係數矩陣中的第n列的值得到的矩陣的行列式的值,即:
| b1 a12 ... a1n |
d1 = | b2 a22 ... a2n |
| ..................... |
| bn an2 ... ann |
| a11 b1 ... a1n |
d2 = | a21 b2 ... a2n |
| ..................... |
| an1 bn ... ann |
...| a11 a12 ...b1 |
dn = | a21 a22 ... b2 |
| ..................... |
| an1 an2 ... bn |
別去點選關閉視窗按鈕!我現在就舉個例子,由於我們現在暫時只討論2-d遊戲(3-d以後會循序漸進的談到),就來個2-d線性方程組:
(1) 4.0*x1 + 2.0*x2 = 5.0
(2) 3.0*x1 + 3.0*x2 = 6.0
這裡有兩個方程,兩個未知量,則根據上面的cramer法則:
| 4.0 2.0 |
d = | 3.0 3.0 | = 4.0*3.0 - 2.0*3.0 = 6.0 (2階行列式的解法,'/'對角線相乘減去'/'對角線相乘)
| 5.0 2.0 |
d1 = | 6.0 3.0 | = 5.0*3.0 - 2.0*6.0 = 3.0
| 4.0 5.0 |
d2 = | 3.0 6.0 | = 4.0*6.0 - 5.0*3.0 = 9.0
則 x1 = d1/d = 3.0/6.0 = 0.5
x2 = d2/d = 9.0/6.0 = 1.5
好了,現在就得到了方程組的唯一一組解。
是不是已經掌握了用cramer法則解2-d線性方程組了?如果是的話,我們繼續。
三、深入研究
這裡的2-d障礙碰撞檢測的實質就是判斷兩條線段是否有交點,注意不是直線,是線段,兩直線有交點不一定直線上的線段也有交點。現在我們從向量的角度,寫出兩條線段的方程。
現在有v1和v2兩條線段,則根據向量加法:
v1e=v1b+ s*v1
v2e=v2b+ t*v2
v1b和v2b分別是兩線段的一端。s,t是兩個引數,它們的範圍是[0.0,1.0],當s,t=0.0時,v1e=v1b,v2e=v2b;當s,t=1.0時,v1e和v2e分別是兩線段的另一端。s,t取遍[0.0,1.0]則v1e和v2e取遍兩線段的每一點。
那麼我們要判斷v1和v2有沒有交點,就讓v1e=v2e,看解出的s,t是不是在範圍內就可以了:
v1e=v2e
=>v1b+ s*v1=v2b+ t*v2
=> s*v1- t*v2=v2b-v1b
寫成分量形式:
s*x_v1 - t*x_v2 = x_v2b - x_v1b
s*y_v1 - t*y_v2 = y_v2b - y_v1b
現在是兩個方程式,兩個未知數,則根據cramer法則:
| x_v1 -x_v2 | | 4.0 -2.0 |
d = | y_v1 -y_v2 | = | 1.0 -3.0 | = -10.0
| x_v2b-x_v1b -x_v2 | | 5.0 -2.0 |
d1 = | y_v2b-y_v1b -y_v2 | = | 2.0 -3.0 | = -11.0
s = d1/d = -11.0/-10.0 = 1.1 > 1.0
現在s已經計算出來,沒有在[0.0,1.0]內,所以兩線段沒有交點,從圖上看很直觀。t沒有必要再計算了。所以是物體與障礙沒有發生碰撞。如果計算出的s,t都在[0.0,1.0]內,則把它們帶入原方程組,計算出v1e或者v2e,它的分量就是碰撞點的分量。
四、理論上的東西已經夠多的了,開始寫程式
我現在要寫乙個用於處理障礙碰撞檢測的函式,為了測試它,我還準備安排一些障礙:
這是乙個凸多邊形,我讓乙個質點在初始位置(10,8),然後給它乙個隨機速度,這個隨機速度的兩個分速度在區間[1.0,4.0]內,同時檢測是否與邊界發生碰撞。當碰撞發生時,就讓它回到初始位置,重新給乙個隨機速度。
//首先我要記下凸多邊形的邊界座標
float poly[2][8] = , //
所有點的x分量,最後乙個點和第乙個點重合
//所有點的y分量
} ;//
定義一些變數
float x , y ; //
這是質點的位置變數
float vx , vy ; //
質點的速度向量分量
//好,開始編寫碰撞檢測函式
bool collisiontest()
//for( int i = 0 ; i < 8-1 ; ++i )
//沒有發生碰撞,返回false
return
false;}
//end of function
//現在對函式做測試
//初始化質點
x = 10.0f , y = 8.0f
;vx = vy = (float)(rand()%4+1
) ;
//進入主迴圈中
//假設現在已經在主迴圈中
if( collisiontest() )
//質點移動
x+=vx ;
y+=vy ;
向量幾何在遊戲程式設計中的使用1
1 簡單的2 d追蹤 andre lamothe說 向量幾何是遊戲程式設計師最好的朋友 一點不假,向量幾何在遊戲程式設計中的地位不容忽視,因為在遊戲程式設計師的眼中,顯示螢幕就是乙個座標 系,運動物體的軌跡就是物體在這個座標系曲線運動結果,而描述這些曲線運動的,就是向量。使用向量可以很好的模擬物理現...
向量幾何在遊戲程式設計中的使用1
1 簡單的2 d追蹤 andre lamothe說 向量幾何是遊戲程式設計師最好的朋友 一點不假,向量幾何在遊戲程式設計中的地位不容忽視,因為在遊戲程式設計師的眼中,顯示螢幕就是乙個座標 系,運動物體的軌跡就是物體在這個座標系曲線運動結果,而描述這些曲線運動的,就是向量。使用向量可以很好的模擬物理現...
向量幾何在遊戲程式設計中的使用1
andre lamothe說 向量幾何是遊戲程式設計師最好的朋友 一點不假,向量幾何在遊戲程式設計中的地位不容忽視,因為在遊戲程式設計師的眼中,顯示螢幕就是乙個座標系,運動物體的軌跡就是物體在這個座標系曲線運動結果,而描述這些曲線運動的,就是向量。使用向量可以很好的模擬物理現象以及基本的ai。現在,...