日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

塔防游戏的路径寻找算法分析

發布時間:2024/8/26 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 塔防游戏的路径寻找算法分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在塔防游戲中,有很多敵人都是向著同一目標前進的。在眾多塔防游戲當中,有一條或幾條預定好的路徑。在一些塔防游戲中,比如經典的《Desktop Tower Defense》,你可以將塔放在地圖上的任何地方,把他們作為阻礙敵人通往預定路徑的障礙。試著點擊地圖來切換或移動墻壁:
?


我們將如何實現?

圖搜索算法例如A*這樣的算法經常被用來搜索兩點之間的最短路徑。你可以用這個來找到每一個敵人前往的目標的路徑。有很多不同的圖搜索算法可以用在這種類型的游戲。這些都是經典的算法:

單源,單目標:
?

  • 貪心搜索算法
  • A*算法 – 在游戲當中常使用


單源多目標或多源單目標
?

  • 廣度優先搜索算法-無加權邊緣
  • Dijkstra算法-有加權邊緣
  • Bellman-Ford算法-支持負權重


多源多目標
?

  • Floyd-Warshall算法
  • Johnson’s算法


像《Desktop Tower Defense》這樣的游戲會有很多個敵人的位置(源)和一個共同的目的地。這使得它被歸為多源單目標這一類。我們可以執行一個算法,一次性算出所有敵人的路徑,而不是為每個敵人執行一次A*算法。更好的是,我們可以計算出每個位置的最短路徑,所以當敵人擠在一起或者新的敵人被創建出來時,他們的路徑已經被預先計算好了。

我們先來看看廣度優先算法,有時也被稱作“洪水填充法”(FIFO的變種)。雖然圖搜索算法是適用于任何由節點和邊構成的網格圖,但是我還是使用方形網格來說明這些例子。網格是圖的一個特例。每個網格瓦片是圖節點,網格瓷磚之間的邊界是圖的邊。我會在另一篇文章當中探討非網格圖。

廣度優先搜索從一個節點開始,并訪問鄰居節點。關鍵的概念是“邊界”,它在已探索和未開發的區域之間的邊界。邊界從原來的節點向外擴展,直到探索了整張圖。

邊界隊列是一個圖節點(網格瓦片)是否需要被分析的列表/數組。它最開始僅僅包含一個元素,起始節點。每個節點上的訪問標志追蹤我們是否采訪過該節點。開始的時候除了起始節點都標志為FALSE。使用滑塊來查看邊界是如何擴展的:
?


這個算法是如何運行的?每走一步,獲得一個元素的邊界,把它命名為current。然后尋找current的每個鄰居,next。如果他們還沒有被訪問過,將他們都添加到邊界隊列里面。下面是一些python代碼:
?

  • frontier = Queue()
  • frontier.put(start)
  • visited = {}
  • visited[start] = True
  • while not frontier.empty():
  • ? ?current = frontier.get()
  • ? ?for next in graph.neighbors(current):
  • ? ?? ?if next not in visited:
  • ? ?? ?? ?frontier.put(next)
  • ? ?? ?? ?visited[next] = True
  • 復制代碼


    現在你已經看見代碼了,試著進入上面的動畫。注意邊界隊列,關于current的代碼,還有next節點的集合。在每一步中,有一個邊界元素成為current節點,它的鄰居節點會被標注,而且沒有被拜訪過的鄰居節點會被添加到邊界隊列。有一些鄰居節點可能已經被訪問過,他們就不需要被添加到邊界隊列里面了。

    這是一個相對簡單的算法,并且對于包括AI在內的很多事情都是有用的。我有三種主要使用它的辦法:

    1.標記所有可達的點。這在你的圖不是完全連接的,并且想知道哪些點是可達的時候是很有用的。這就是我再上面用visited這部分所做的。

    2.找到從一個點到所有其他點或者所有點到一個點的路徑。我在文章開頭的動畫demo里面使用了它。

    3.測量從一個節點到所有其他節點的距離。這在預先知道一個移動中的怪物的距離時是很有用的。

    如果你正在生成路徑,你可能會想知道從每個節點移動的方向。手機號賣號當你訪問一個鄰居節點的時候,要記得你是從哪個節點過來的。讓我們把visited重命名為came_from并且用它來記錄之前位置的軌跡:

  • frontier = Queue()
  • frontier.put(start)
  • came_from = {}
  • came_from[start] = None
  • while not frontier.empty():
  • ? ?current = frontier.get()
  • ? ?for next in graph.neighbors(current):
  • ? ?? ?if next not in came_from:
  • ? ?? ?? ?frontier.put(next)
  • ? ?? ?? ?came_from[next] = current
  • 復制代碼


    我們來看看它是這樣的:
    ?


    如果你需要距離,你可以在起始節點將一個計數器設置為0,并在每次訪問鄰居節點的時候將它加一個鄰居節點。讓我們把visitd重命名為distance,并且用它來存儲一個計數器:
    ?

  • frontier = Queue()
  • frontier.put(start)
  • distance = {}
  • distance[start] = 0
  • while not frontier.empty():
  • ? ?current = frontier.get()
  • ? ?for next in graph.neighbors(current):
  • ? ?? ?if next not in distance:
  • ? ?? ?? ?frontier.put(next)
  • ? ?? ?? ?distance[next] = 1 + distance[current]
  • 復制代碼


    我們來看看它是這樣的:
    ?


    如果你想同時計算路徑和距離,你可以使用兩個變量。

    這就是廣度優先檢索算法。對于塔防風格的游戲,我用它來搜尋所有位置到一個指定位置的路徑,而不是重復使用A*算法為每個敵人計算路徑。我用它來尋找每一個移動的怪物的指定行動距離內所有的位置。我也是用它來進行程序化地生成地圖。Minecraft使用它來進行可見性剔除。這是一個好的算法。

    接下來的步驟:

    我有實現python和c++代碼。

    如果你想要找到從一個點出發而不是到達一個點的路徑,只需要在檢索路徑的時候翻轉came_from指針。

    如果你想要多個點路徑而不是一個點的路徑,你可以在圖的邊緣為你的每個目標點添加一個額外的點。額外的點不會出現在網格中,但是它會表示在圖中的目標位置。

    提前退出:如果你是在尋找一個到達某一點或從某一點出發,。我在A*算法的文章當中描述了這種情況。

    加權邊:如果你需要不同的移動成本,廣度優先搜索可以替換為為Dijkstra算法。我在A*算法的文章當中描述了這種情況。

    啟發:如果你要添加一種指導搜索目標的方法,廣度優先算法可以替換為最佳優先算法。我在A*算法的文章當中描述了這種情況。

    如果你從廣度優先算法,并且加上了提前退出,加權的邊緣和啟發,你會得到A*。正如你所想,我在A*算法的文章當中描述了這樣的情況。

    總結

    以上是生活随笔為你收集整理的塔防游戏的路径寻找算法分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。