聊聊用演算法生成《率土之濱》的世界地圖

王鑫然發表於2022-04-15
聊聊用演算法生成《率土之濱》的世界地圖

作者:王鑫然
首發知乎https://zhuanlan.zhihu.com/p/260771031

之前做戰爭策略遊戲的時候,有過讓大地圖通過演算法隨機生成的想法,但由於各種原因,想法終沒實現。現在剛好有空想想這個問題,做做思路積累。也藉著這篇文章,講講演算法方面的東西。

在傳統的SLG戰爭策略類手遊中,玩家要不斷地探索大地圖,向外擴張領土,擊殺野怪和其他玩家,大世界地圖上哪個地方是草,哪個地方是山,哪個地方是河流,都是手動一個區域一個區域的調出來的, 在《率土之濱》中同樣如此,大地圖的佈局固定,每個伺服器都一樣,導致每個伺服器大地圖上的戰略戰術也一樣。但如果希望每個伺服器的大地圖戰略戰術都不同,用演算法該怎麼去實現這個東西?

演算法要實現的東西

固定的位置模組

在《率土之濱》的初始地圖中,有10多個區域,這些區域之間存在邊界,屬於固定區域。區域間通過固定位置的橋樑或關隘進行連線。區域內部有固定座標的城市、要塞爭奪點。再算髮生的大地圖的過程中,要把這些有固定位置設計需求的元素考慮進去。

聊聊用演算法生成《率土之濱》的世界地圖

區域邊緣

如果整張地圖用演算法進行連續運算,生成地貌,那麼在區域的邊界處,可能會出現一座面積龐大且連續的、不可通行的大山,而實際上在區域的邊界處,我們僅僅需要一條細細的河流來分割區域.

聊聊用演算法生成《率土之濱》的世界地圖

地圖模組種類的均衡

《率土之濱》中主要包含兩種地圖模組,一種是資源型地貌模組,一種是不可通行地貌模組,等級越高的資源模組,其分佈越稀疏,數量越少。同等級的幾種資源模組之間的數量需要保持地區分佈均衡。

聊聊用演算法生成《率土之濱》的世界地圖

玩家獲得資源的平衡

如果分佈在不同玩家周圍的資源數量不同,則會拉開前期發展速度的差距,讓一部分玩家輸在了起跑線上,所以演算法應該保證玩家城市生成座標附近,同等級的初始資源上的均衡,這包含數量上的均衡,以及距離上的均衡。

玩家的地區密度

一個地區如果玩家的密度過大,勢必導致遊戲前期,在這個地區內發生的PVP頻率過高,玩家在前期沒有安全穩定發展的公平環境,導致玩家密度高的地區,在遊戲前期的流失率遠高於玩家密度低的地區。

聊聊用演算法生成《率土之濱》的世界地圖

地圖的生成

地圖演算法層

地圖演算法層分為成像層和承載層,成像層用於生成地圖的地貌引數,承載層用於生成玩家真實在遊戲裡看到的地表上的各種物體,承載層內包含有地格層,地表基色層,資源和不可通行層、怪物層等多個演算法層。

基本輪廓生成

地圖輪廓的生成,用到perlin噪聲,perlin噪聲的兩個重要引數是“振幅”和“頻率”,將多個perlin噪聲函式疊加起來後,就可以生成一個連續且更加自然的函式影像。

聊聊用演算法生成《率土之濱》的世界地圖

應用在空間直角座標系後的影像大概是這樣。

聊聊用演算法生成《率土之濱》的世界地圖

在一些戰爭策略類遊戲中,大地圖可能被設計成整片的海洋,陸地則被設計成孤島,這個時候可以利用“種子生長”,從一點開始向外展開陸地。

山脈、河流、草地的定義和生成

在《率土之濱》裡,地形塊以格為單位,分為資源地塊(平原)、山脈地塊、河流地塊,這三種基本地塊(其他地塊型別自行腦補),通過高度的定義,我們可以將perlin噪聲所生成的影像下的地塊,定義為這3種型別,如在空間直角座標系中,我們將Z≥2的稱為山脈,0<Z<2稱為資源地塊,將Z≤0的稱為河流地塊。以此定於地塊。

遊戲裡為了讓玩家對不同地塊有更加清晰的認知,通常會用形狀相同的素材來表示一類東西,比如山脈的形狀都一樣,頂多分幾個不同的素材來表示山脈,所以真實遊戲裡生成的大概是這樣。

聊聊用演算法生成《率土之濱》的世界地圖

區域的劃分

在2維座標中,在X軸上劃定一個區域,就可以規定一個函式影像的範圍,在空間直角座標系中,用一個矩形就可以劃定一個區域,無數個形狀不同的矩形疊加在一起,則可以劃定一個形狀不規則的區域,函式的影像則在這個區域內生成

聊聊用演算法生成《率土之濱》的世界地圖

區域邊緣的處理

規定區域的邊緣為山脈地形塊或河流地形塊,並從這個地形塊開始向外隨機延伸地形塊,延伸的地形塊數值為0到3,對每一個隨機值設定一個權重,如果想讓地圖邊界附近有更多的山脈包圍,則可以讓3的權重更大,如果想讓地圖邊界附近有更多的可通行區域,可以讓0的權重更大。數值代表向邊界外延伸多少個不可通行的地形塊。地形塊的型別以邊界上的地形為基準進行對映,比如邊界是河流的,則附近延伸的地形對應為山脈。

聊聊用演算法生成《率土之濱》的世界地圖

固定點的處理

《率土之濱》裡的城市、要塞,屬於固定點,這些點周圍的區域要保持為可通行的資源地塊狀態,所以perlin噪聲所生成的高低起伏的影像,不應該影響到這裡的地形。在空間直角座標系中,如果要形成一個高低起伏的地形,則先要給矩形網格中的點,隨機生成一個單位圓梯度,再用方向向量與網格點的梯度向量做點積,最後對單個矩形四個點進行加權,得到該計算點的數值,使得數值在區域內平緩過渡,從而繪製出噪聲圖譜,如果不希望一個區域有高低起伏,可以直接控制這個區域內網格點向量的角度。

聊聊用演算法生成《率土之濱》的世界地圖

“回”型區域的識別

在中間是可通行區域,周圍是不可通行區域的地形稱為“回”字型區域,回字型區域可以偶爾出現,但數量一多,就說明生成的地圖是有問題的,回字型區域的數學特點是——中間地塊沒有路徑通向到所有的關鍵點(關鍵點可以取關隘),用“廣度優先搜尋”演算法可以表示出路徑可通行狀態和路徑長度。

聊聊用演算法生成《率土之濱》的世界地圖

“桶”型區域的識別

這種地形的數學特點是——中間的點與其相鄰的“筒壁”上的點,距離關鍵點的距離差很大,用“廣度優先搜尋”演算法計算出每一個點距離每一個關隘的距離,根據連續多個點的距離差的大小,可以識別這種地形。

聊聊用演算法生成《率土之濱》的世界地圖

資源地塊的分佈

如果資源地塊的距離過近,就會在某個地方形成資源田的聚集,導致這個區域的PVP壓力增大,《率土之濱》的外圍州,屬於初始區域,這個區域中,玩家要進行前期的發展,需要更加和平穩定的資源採集環境,所以要均衡這些地區的資源分佈,可以利用“泊松圓盤”來構建這種分佈。

聊聊用演算法生成《率土之濱》的世界地圖

用“米切爾最佳候選”演算法,可以近似的構建“泊松圓盤”,這種演算法是從一堆候選取樣點中選取一個最佳取樣點。做法是,第一輪先撒一堆點,這個點稱為“已固定取樣點”,之後在取樣區域內隨機生成固定數量的“候選取樣點”。在“已固定取樣點”和“候選取樣點”之間畫一條線,線段長度記為M,最終從“候選取樣點”中選出一個M值最大的點,作為“最佳候選取樣點”。第一輪結束後,“最佳候選取樣點”被標記為“已固定取樣點”,之後繼續下一輪,不斷迴圈,直到充滿整個樣本地圖。

聊聊用演算法生成《率土之濱》的世界地圖

最終選出一堆“已固定取樣點”,作為資源分佈點,不同等級的資源點則在資源分佈點中按照給定比例隨機分佈。

玩家分佈

在《率土之濱》中,玩家的初始城市會佔掉地面3*3的格,所以玩家之間初始城市中心座標的最小地塊直線距離是5格(沒有半格的概念,中間留一格為了美觀)。以任意玩家的城市中心點為中心,直徑為5,畫一個圓,也就是說,在這個圓內不能出現其他玩家的初始城市座標。

聊聊用演算法生成《率土之濱》的世界地圖

同時,需保證每名玩家初始城市周圍的資源數量保持一定範圍內的均衡,在《率土之濱》中,資源地塊的數量遠遠大於玩家的數量,所以可以利用已選出的“資源分佈點”,取樣出所有臨近點之間距離大於等於5的點,作為玩家初始城市座標的生成樣本。


原文:https://zhuanlan.zhihu.com/p/260771031

相關文章