1. 追逐/閃躲的組成
完整追逐/閃躲由三部分組成:
·作出追或逃的決策判斷(在後文談論到狀態機器和神經網路時,再討論)
·開始追或逃(本章重點)
·避開障礙物(第五章和第六章,再討論)
2. 基本追逐和閃躲
假設:追逐者座標(predatorX, predatorY),閃躲者座標(preyX,preyY)
連續環境的基本追逐代碼
if(predatorX > preyX) predatorX--;
else if(predatorX < preyX) predatorX++
if(predatorY > preyY) predatorY--;
else if(predatorY < preyY) predatorY++
連續環境的基本閃躲代碼
if(preyX > predatorX) preyX++;
else if(preyX < predatorX) preyX--;
if(preyY > predatorY) preyY++;
else if(preyY < predatorY) preyY--;
磚塊環境的基本追逐/閃躲代碼與連續環境的十分類似,這裡忽略。
3. 視線追逐
3.1 磚塊環境中,為什麼要視線追逐
圖-磚塊環境中的簡單追逐和視線追逐
左邊的是簡單追逐的映像,右邊的是視線追逐的映像。
簡單追逐算出來的肯定是最短的路徑,但是不一定能夠求得視覺上的直線,而直線追逐在視覺上會好很多。
另外,如果有一群攻擊者往玩家處聚攏時,簡單追逐會使得,在以目標為遠點的座標系中,他們沿著對角線走到距離最近的座標軸,然後再沿著該座標軸走向目標。這樣就相當於讓他們排成一個縱隊發起攻擊。更加合理的做法是,分別從不同方向向目標逼近。
3.2 磚塊環境中,如何?視線追逐
書中使用的是所謂的Bresenham演算法,該演算法是在圖素環境中畫線最有效方法之一。最原始的Bresenham需要除法計算斜率,但是簡化版本的Bresenham,利用乘法避免了減法的應用。
首先,Bresenham確實是比較好的演算法,因為它能夠保證整條路徑的近似在一條直線上。而不簡單的是把兩種步子均勻化,可以說Breseham更具有大局觀。
Bresenham的演算法參見http://blog.sina.com.cn/s/blog_4b194f4f0100crbj.html,其中講的很好,只是注意其中關鍵的d-1的部分,其實是因為向右上方移動了,y座標加1,所以需要減1。把其中的公式乘以Dx,就能得到不需要除法的推導過程了。
3.2 連續環境中的視線追逐
這一小節討論的連續環境中的視線追逐是最簡單的追逐演算法,不過考慮了追逐者得移動不僅有線速度,還有角速度。演算法思路就是,首先根據角速度把方向轉到視線方向,然後向目標追過去。這一節中的更多的是介紹全域座標系統和局部座標系統。
圖-座標系統
局部座標系統怎麼構造呢,即局部構造系統的x軸,y軸方向怎麼確定的呢。其實就是認為追逐者當前的移動方向是y軸的正方向(當前追逐者靜止咋辦呢?這個還不知道),x軸正方向是y軸正方向逆時針旋轉90度得到。座標轉化關鍵是那個夾角。根據上面的公式,把追逐者的全域座標(X',Y')和局部座標(0,0)帶入,就能算出來夾角的餘弦和正弦值了。實際上,使用局部座標系,是因為有現成的函數可以協助座標進行座標系轉化,而座標轉化後,使用起來更加方便了。從下面代碼中也能發現,即在判斷向左轉還是向右轉的時候,只需要判斷視線向量的x座標的正負即可,當然這裡的方便性與前面局部座標轉化的參數有很大關係即-Predator.fOrientation,具體的還不清楚,沒接觸過VRotate2D這個函數。
void DoLineOfSightChase(void)
{
Vector u,v; // u追逐者向量,v獵物向量
bool left = false; // 是否需要向左轉
bool right = false; // 是否需要向右轉
u = VRotate2D(-Predator.fOrientation,
Prey.vPosition-Predator.vPosition) // 視線在局部座標系中的向量
u.Normalize(); // 歸一划
if(u.x < -_TOL) // 判斷轉動的方向
left = true;
else if(u.x > _TOL)
right = true;
Predator.SetThrusters(left, right); // 轉動
}
4. 攔截
攔截演算法的基本原理是能夠預測獵物未來的位置,然後直接到那個位置去,是其能和獵物同時到達同一位置。為了找出追擊者和獵物能同時到達的點,不僅要考慮他們的移動方向,還要考慮他們的速度。其實很簡單,首先預測追擊者追到獵物的最短時間,即,靠攏時間=相對位移/相對速度,如果追擊者不能改變方向的話,靠攏時間可能不存在,比如相對位移與相對速度方向相反,這就永遠都不可能靠攏,這一小節的最後對這種情況進行了簡單說明。有了靠攏時間,就能根據獵物的速度和初始位移,預測到其在靠攏時間後的位置,這樣追擊者只有根據這個位置,採用前面的視線法追擊這個位置就好了。
這個攔截演算法對嗎?感覺還是有問題,根據書中說法,獵物和追逐者的速度向量和位移向量都是固定的,因為靠攏時間的計算,需要相對位移和相對速度。但是如果這些都是固定的話,很容易得到兩者很可能不會相遇的問題。更近合理的解釋應該是獵物的速度向量和初始位置向量固定,追逐者的初始位置和速度大小固定,而速度方向不固定,這樣通過調整方向來達到攔截的作用。計算可以採用靠攏時間的方法,不過是一個方程。
5. 總結
這一章給出的還是一些基礎方法,第5章還會說明利用勢函數進行追逐或閃躲。
6. 實踐
附件中是我自己實現的磚塊環境中的視線追逐,其中有三個演算法可選,第一個是基本方法,第二個是bresenham方法,第三個是用除法和模數運算視線的方法。後兩種方法在一些情況下很很相似,當然也有不同的,個人感覺還是bresenham更好一些,畢竟有理論支援。
磚塊環境中的追逐示範程式:http://files.cnblogs.com/pangxiaodong/chasing.swf
程式:
圖-磚塊環境中的視線追逐示範