在游戲中尋路是無處不在的。最著名的尋找最短路徑算法莫過與A*算法,實現方式有很多中,重要的是我們要掌握其原理。
在本教程中,我們將介紹一種相對較新的方法搜索——基於網格的世界的跳點的搜索,可以加速A*尋路算法。效率提升那是大大的。
我假設讀者已經明白A*算法的原理。如果你對A星尋路還不是很了解的話,我推薦你去看下這篇十分簡單明了的教程,了解A星算法原理,猛戳這里。
好的,下面進入正題,開始講解Jump Point Search!(以下簡稱JPS)
先來看個Demo,做個對比實驗
首先讓我們來看下老外用AS開發的一個Demo。Demo中黑色部分為不可行走區域,鼠標放到場景中任何個點,都會進行尋路算法,左上角的文本會提示尋路算法平均花費時間。
按【空格】鍵可以切換尋路算法模式為普通A*算法和JPS優化后的A*算法。
按【A】鍵可以添加NPC(貌似瓢蟲的動物)
按【R】鍵可以移除NPC
下面開始講解原理
常規A*算法,是向相鄰的格子中搜索可能的“最近節點”,然后把所有的“最近節點”連接起來,既為最終解。至於說怎樣的節點才是“最近節點”,本篇不做介紹,因為我前面已經設定了讀者是已經明白A*算法的原理的了。
問題的關鍵,就在於,我們一定要逐格逐格的去搜索嗎?隨着格子密集度提升,時間復雜度也將大幅提升。
那么我們如何去優化呢?
很簡單,對於大片的可行走區域,他們之間的任何一點都是可聯通的,我們可以省去這部分格子的“最近節點”搜索,這將是很大一部分的搜索的運算了。我們只需要找出一些相關的控制點,然后通過控制點之間的連通,省去大部分無謂的“尋找最近節點”的運算。
具體思路如下:
1 生成/擺放好 凸多邊形障礙物
2 “擴展”多邊形 擴展的大小取決於 尋路者的大小
3 將地圖中所有聯通點(以擴展后的多邊形為主)構成一張”圖”
4 將尋路者的起點和目標點作為”臨時節點”加入到3)中生成的圖里
5 在圖中尋路. 尋路后將之前的起點移除.
下面我們舉個例子:
1、有如下一張地圖,途中黑色填充為不可行走區
2、 “擴展”多邊形 擴展的大小取決於 尋路者的大小,如圖中細線部

3、將地圖中所有聯通點(以擴展后的多邊形為主)構成一張”圖”
4 、將尋路者的起點和目標點作為”臨時節點”加入到3)中生成的圖里
5、基於圖中的“控制點” ,在圖中尋路.
5.1、尋路第一步,將起始點作為搜索點,在與其相鄰的控制點中,找到可能的“最近節點”,如圖所示,最粗的兩條線的交點,就是我們要找的“最近節點”,因為其深綠色線段+淺綠色線段的長度之和,是最短的。這也是A*尋路的基本思路。
5.2、尋路第二步,把上一步尋找到的“最近節點”,作為新的搜索點,然后重復同樣的判斷,找到新的新的“最近節點”,如圖所示,紅色的點,就是我們要找的新的“最近節點”
5.3、尋路第N步,重復同樣的算法,尋找新的可能的“最近節點”,直到找到“終點”。如下圖,深綠色的路線,就是我們尋路結果。
總結:
看到這里,我想大家一定都懂了,也肯定明白了,為什么利用JPS算法能夠大大提高A*尋路的效率。因為它省去了一些無謂的判斷節點。當然它是需要在尋路之前,開銷一些空間和時間去進行地圖的預處理。不過這點開銷,在后面尋路算法中又大大地賺了回來。
附錄:
在這里提供一個HTML5寫的Demo,需使用兼容HTML5的高富帥瀏覽器,方能運行,屌絲IE6請繞道。猛戳這里。可以更加清晰的體現Jump Point Search算法的輪廓。
我的微博:@我就叫向佳
感謝@大城小胖
【轉自】http://www.36haojie.com/index.php/2013/08/jumppointsearch/
