很多游戲特別是rts,rpg類游戲,都需要用到尋路。尋路算法有深度優先搜索(DFS),廣度優先搜索(BFS),A星算法等,而A星算法是一種具備啟發性策略的算法,效率是幾種算法中最高的,因此也成為游戲中最常用的尋路算法。
直入正題:
在游戲設計中,地圖可以划分為若干大小相同的方塊區域(方格),這些方格就是尋路的基本單元。
在確定了尋路的開始點,結束點的情況下,假定每個方塊都有一個F值,該值代表了在當前路線下選擇走該方塊的代價。
而A星尋路的思路很簡單:從開始點,每走一步都選擇代價最小的格子走,直到達到結束點。
A星算法核心公式就是F值的計算:
F = G + H
F - 方塊的總移動代價
G - 開始點到當前方塊的移動代價
H - 當前方塊到結束點的預估移動代價
以下詳細解釋這個公式,方便更好地理解它。
G值是怎么計算的?
假設現在我們在某一格子,鄰近有8個格子可走,當我們往上、下、左、右這4個格子走時,移動代價為10;當往左上、左下、右上、右下這4個格子走時,移動代價為14;即走斜線的移動代價為走直線的1.4倍。
這就是G值最基本的計算方式,適用於大多數2.5Drpg頁游。
基本公式:
G = 移動代價
根據游戲需要,G值的計算可以進行拓展。如加上地形因素對尋路的影響。格子地形不同,那么選擇通過不同地形格子,移動代價肯定不同。同一段路,平地地形和丘陵地形,雖然都可以走,但平地地形顯然更易走。
我們可以給不同地形賦予不同代價因子,來體現出G值的差異。如給平地地形設置代價因子為1,丘陵地形為2,在移動代價相同情況下,平地地形的G值更低,算法就會傾向選擇G值更小的平地地形。
拓展公式:
G = 移動代價 * 代價因子
H值是如何預估出來的?
很顯然,在只知道當前點,結束點,不知道這兩者的路徑情況下,我們無法精確地確定H值大小,所以只能進行預估。
有多種方式可以預估H值,如曼哈頓距離、歐式距離、對角線估價,最常用最簡單的方法就是使用曼哈頓距離進行預估:
H = 當前方塊到結束點的水平距離 + 當前方塊到結束點的垂直距離
題外話:A星算法之所以被認為是具有啟發策略的算法,在於其可通過預估H值,降低走彎路的可能性,更容易找到一條更短的路徑。其他不具有啟發策略的算法,沒有做預估處理,只是窮舉出所有可通行路徑,然后從中挑選一條最短的路徑。這也是A星算法效率更高的原因。
每個方塊的G值、H值是怎么確定的呢?
G值 = 父節點的G值 + 父節點到當前點的移動代價
H值 = 當前點到結束點的曼哈頓距離
最后,A星算法還需要用到兩個列表:
開放列表 - 用於記錄所有可考慮選擇的格子
封閉列表 - 用於記錄所有不再考慮的格子
以上就是要完成A星算法所需要的東西,而算法的過程並不復雜。
A星算法偽碼:
a、將開始點記錄為當前點P
b、將當前點P放入封閉列表
c、搜尋點P所有鄰近點,假如某鄰近點既沒有在開放列表或封閉列表里面,則計算出該鄰近點的F值,並設父節點為P,然后將其放入開放列表
d、判斷開放列表是否已經空了,如果沒有說明在達到結束點前已經找完了所有可能的路徑點,尋路失敗,算法結束;否則繼續。
e、從開放列表拿出一個F值最小的點,作為尋路路徑的下一步。
f、判斷該點是否為結束點,如果是,則尋路成功,算法結束;否則繼續。
g、將該點設為當前點P,跳回步驟c。
后續優化
以上就是A星算法最基本的原理,明白了基本原理,用2,3百行代碼寫出一個可用的A星算法並不難。當然A星算法在實際應用中不僅於此,還可以對細節進行優化:
1、選擇排序更快的二叉樹來作為開放列表,幫助我們更快地從開放列表中取出F值最小的點;
2、對何種情況下可以走斜線路徑加以判斷;
3、采用布蘭森漢姆算法預先判斷兩點是否可以直接通行,可通行就直接返回兩點的直線路徑,不可直接通行再采用A星算法尋路,提高尋路效率;
4、A星算法得出尋路路徑后,可采用弗洛伊德算法對路徑進行平滑處理,使人物走動更為自然
這里只是用語言講解A星算法原理,並沒有配圖講解整個尋路的過程,希望進一步直觀理解整個過程的,推薦參考下面兩個網友翻譯過來的A星教程
http://www.raywenderlich.com/zh-hans/21503/a%E6%98%9F%E5%AF%BB%E8%B7%AF%E7%AE%97%E6%B3%95%E4%BB%8B%E7%BB%8D
http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx