創作內容

4 GP

遊戲物理,數學~向量的功用

作者:willyliu│2009-07-31 23:26:19│巴幣:1,006│人氣:2805
在遊戲物理,遊戲數學中,向量起了很大的功用,尤其是物體碰撞偵測,反應的問題
它能解決一些無限大的問題,補足斜率的缺陷,也能使演算法更簡潔,程式碼更乾淨

首先,來介紹(或複習)高中數學吧!
先從簡單的2維向量下手:
向量,就是一個向加一個量,可以把它想成一個箭頭:
向,即方向,就是箭頭指向哪
量,即長度,箭頭有多長
向量的加法,就是把兩個箭頭連在一起,再把其中一個尾巴連到另一個的頭:
→+↓ = → = \
    ↓   ↘
(請兩行一起看)

負的向量,就是把箭頭反過來:
-↓ = ↑
那麼,減法就簡單了,就是"加負的":
↑-← = ↑+(-←) = ↑+→

好,基本圖形概念已經結束了,現在換成抽象一點的形式-數字
n維度的向量可以表示成這樣:[x1,x2,x3......xn]
x後面的數字代表第幾個維度,以xy平面來說,是這樣[x,y]
也就是說:x是第一個維度,y是第二個維度
換成圖形(箭頭),x和y就可以想像成在座標軸上的(x,y),向量[x,y]就是由(0,0)指向(x,y)

向量的加法,是把兩個向量的各維度分別加起來,減法亦然
A=[1,2,3] B=[4,5,6] 那麼A+B=[1+4 , 2+5 , 3+7]
簡單吧!

現在~請集中精神,牢牢記下下面的每一個重點
向量的第一個主角要登場了:內積,又稱純量積,點積

while 你還沒記起來
then
定義:A=[a1,a2,a3] B=[b1,b2,b3] 內積A●B = a1*b1 + a2*b2 + a3*b3
把各維度分別相乘,再加起來,
注意,內積之所以叫純量積,是因為它乘起來後是個純量(也就是一個數字),而非向量
關於內積的重要式子:A●B = ∥A∥ ∥B∥cosθ
其中,∥A∥代表向量A的長度,是個正數,θ是兩向量的夾角
done

你走出迴圈了嗎?還沒記起來的話不要亂break喔!

很明顯地,我們可以看到,要是夾角為90°,cosθ便會是0,內積也會是0
而夾角<90°,cosθ會<0,內積也<0,因為長度∥A∥ ∥B∥恆正
然後,夾角>90°,內積就會<0
結論是:夾角越小,內積越大

現在,請把箭頭的那些玩意兒自行推廣到3維,也就是[x,y,z]立體的向量,不管你是否只萌二次元
一樣只是個箭頭,加法還是頭接尾,內積還是兩箭頭的夾角越小值越大
腦中建構好之後,可以往下看了

第二主角:外積,又稱向量積,外積
你應該知道了吧!因為它叫向量積,所以乘起來是個向量
一樣,請進入while迴圈:

while 你還沒記起來
then
定義:A=[a1,a2,a3] B=[b1,b2,b3] 外積AXB = [a2*b3-a3*b2 , a3*b1-a1*b3 , a1*b2-a2*b1]
把各維度交叉相乘
關於外積的重要式子:∥AXB∥ = ∥A∥ ∥B∥sinθ
圖形的話是(請將你的右手開掌):
右手拇指指向箭頭A,其他四指指向箭頭B,掌心就是AXB的方向了
方向知道了,而大小是A,B兩向量為鄰邊所構成平行四邊形的面積
done

公式很難記嗎? 這裡有一個比較好理解的方式:
A=[a1,a2,a3] B=[b1,b2,b3]
i j k
a1 a2 a3
b1 b2 b3
向↘這個方向乘起來,再減掉↙這個方向乘起來
首先↘這個方向有3個:i * a2 * b3 和 j * a3 * b1 和 k * a1 * b2 ,把它們相加....(1)
然後↙這個方有向3個:i * a3 * b2 和 j * a1 * b3 和 k * a2 * b1 ,把它們相加....(2)
用(1) - (2),得到:(a2 * b3 - a3 * b2)i + (a3 * b1 - a1 * b3)j + (a1 * b2 - a2 * b1)k
i,j,k分別代表x,y,z的方向,前面的括弧則是它們的分量

外積還有個重點:不具交換律
若把它反過來乘,則右手拇指和其他四指的所指的向量要對換,掌心方向(外積方向)會相反
也就是說AXB = -BXA

最後,看到∥AXB∥ = ∥A∥ ∥B∥sinθ這個式子,
θ = 0°或180°時 sinθ = 0
θ = 90°時外積最長

以上,請全不弄熟了,才能看應用,若還是不熟,看維基百科吧:純量積,向量積

------------------------------終於要進入應用部分了,這是偉大的分隔線---------------------------------------------

在2D的遊戲世界中,先想像一個系統:一顆球和一條直線
直線不會動,球則以固定速度移動
我們知道直線上的其中兩點座標,和球的位置,速度
問題來了:
1.球和線甚麼時候會相撞?
2.如果碰撞後沒有能量損失,線不移動,且遵守入射角=反射角,碰撞後球的速度為何?

第一題普遍的解法:
1.把直線,和球的速度換成斜率,和與y軸的截距,再算出交點
2.利用兩線的斜率,帶入反三角函數算出夾角
3.把球的半徑除上sinθ得到碰撞時的球心和"球速度,直線交點"的距離
4.把此距離用球速度的斜率球出x,y分量,再算出碰撞時球的位置
5.把球線在位置指向碰撞時球的位置的向量除以球速度,得到碰撞時間

很好,很複雜,投影來投影去的,又加上一堆討厭的斜率
這個解法可能正確,但潛在兩個問題:
1.斜率只是一條直線,沒有前後方向之分(角度+180°相反後,斜率相同),產生正負號問題
2.斜率在"平行y軸"時為無限大,無限大在計算時會跑出一堆意想不到的bug

這時候,向量派上用場了:
做法如下:
1.把直線分出"首,尾"讓它有個方向(至於哪邊首,哪邊尾,都可以,記住就好)
2.設"直線尾端指向球的'位置(t)'(位置為時間的函數)"為向量A,"直線尾端指向直線首端"為向量B
3.計算∥AXB∥ / ∥B∥ = 球半徑 ,此方程式的解t即為碰撞時間,應該有2個解,依AXB的z分量正負號分辨

對向量外積不熟的人,一定聽得霧煞煞
首先,因為這是2D的情況,所以A,B的z分量必為0
所以外積變成:
i j k
a1 a2 0
b1 b2 0
而只有k * a1 * b2 和 k * a2 * b1這兩項非零了
也就是說:AXB是個純粹只向z或-z的向量,它的x,y分量皆為0
然後因為∥AXB∥ = ∥A∥ ∥B∥sinθ
所以∥A∥sinθ = ∥AXB∥ / ∥B∥
而∥A∥sinθ就是球心位置到直線的距離(垂直距離)
所以,∥AXB∥ / ∥B∥ = 球半徑 這個方程式說明了在碰撞時,球心距離直線恰為球的半徑,解出t就是時間了
最後,我們利用向量外積AXB = -BXA這個特性分辨方向,當初說要記住頭尾方向用處就在這邊了!
怎麼分辨?外積的z分量的符號就分別代表了箭頭的左邊或右邊了(面向箭頭方向的左邊,右邊)

第一題,我們利用向量避開了斜率的無限大和方向性問題,而且不需要計算三角函數!
Flash ActionScript的Source在這:
function hitSegmentTest(rDTO:RouteDTO, sDTO:SegmentDTO, isRightLine:Boolean):Vector.<Number>
{
var dx:Vector.<Number> = rDTO.x.slice();
dx[0] -= sDTO.sx;
var dy:Vector.<Number> = rDTO.y.slice();
dy[0] -= sDTO.sy;
var crossProduct:Vector.<Number> = Equation.substract(Equation.multiply(dy, sDTO.dx), Equation.multiply(dx, sDTO.dy));
var equation:Vector.<Number> = Equation.multiply(crossProduct, 1 / sDTO.length);
equation[0] += isRightLine? -rDTO.radius: rDTO.radius;
var result:Vector.<Number> = Equation.solve(equation);
return result;
}
這邊要稍為說明一下,因為會用到其他函式,而我沒列出
首先,引數的rDTO,sDTO分別記錄了球,直線的資料,
isRightLine這個布林決定回傳的結果為球在線的右側(true)或左側(false)碰撞的結果
sx,sy為直線的根,ex,ey為直線的頭,vx,vy為球的速度分量,陣列x的生成函數為x(t) ,y亦然
Equation類別存放了一些數學的公用函式
Equation.substract為陣列生成函數的減法,multiply為乘法
equation陣列的意義為:"其生成函數=0"這個方程式,solve回傳其數個解的陣列
Vector是甚麼?和C++的STL一樣,見前面發的說明文章

第二題,很抱歉,我有點累了...有空再打XD
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=247982
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:|數學|Flash|ActionScript|program|programming|程式設計|程式|

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

4喜歡★a27268139 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:人工智慧演算法~A*... 後一篇:數資班啊數資班...

追蹤私訊切換新版閱覽

作品資料夾

flys8028大家
小小美食部落格,歡迎來看看歐 https://www.fatnyanya.com/看更多我要大聲說昨天08:02


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】