程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 游戲大世界場景(胡謅篇)

游戲大世界場景(胡謅篇)

編輯:C++入門知識

科比:“你知道凌晨4點的洛杉矶是什麼樣子嗎?”

IT男:”哦,那個點我還在加班“

科比:“。。。哦,那沒事了“

這個段子反應了國內程序員們說不出的苦逼,我也正是因為昨天在公司看到了凌晨4點的景象,所以今天才能在家騰出時間來整理些平時沒空整理的東西,也算是在不清醒的狀態下胡謅一下吧

早晨像狗一樣爬起來後,漫無目的地浏覽著硬盤,在抵擋住一個個神秘文件夾的誘惑之後,居然翻出了幾年前珍藏的wow的視頻,一打開就是看了一個多小時,看完之後不免世俗地感歎了一番時光流逝之快,以前頹廢於wow的景象歷歷在目,那真是一段特殊的經歷,雖然沉溺,但回想起來卻沒有一絲罪惡,也不後悔,反而更多的是溫馨和懷念,也許真的是工作時間久了,反而對虛擬世界有了眷戀。自己也曾思考為什麼會對wow如此有情節,拋開游戲產品本身的優劣,也許是因為當時國內的游戲環境還沒有太多的利益沖突,史玉柱的免費網游模式還未鋪天蓋地地席卷中國大陸,在相對公平的時間消費的基礎上,大家都是在互幫互助,一起體驗游戲,那真是游戲人生中的一段高光了,少了真實生活中的爾虞我詐,略顯不真實,但卻快樂,可惜今後可能永遠不會體驗到了

========================== 扯淡分割線 =============================

標題提醒著我不能再扯淡下去,要不然觀眾就會埋怨還不進入正題。關於游戲大世界場景這個話題,我一直在思考,不同的公司,不同的項目,我都在思考倘若要做一個如wow般的大世界應該如何著手,這也是我上面談到wow的理由,從技術上來講,wow也帶給中國市場太多新技術了 – 真正的大世界感覺的場景,雲風曾經提到過的相位技術,以及lua的普及

我個人目前的經驗來說,做一個大世界場景,有這麼幾個難點需要克服:

1)附近實體的搜索

2)AI地圖尋路

3)不同地圖上計算實體的負載

難點1:

對於一般的2D平面游戲,可以將地圖按某一定大小的塊進行劃分(partition),尋找附近實體的附近轉變為尋找附近單元,這裡可以用到的數據結構可以是四叉樹(quad-tree),如果是3D場景,那麼將是一顆八叉樹(octree),在尋找到附近單元後,再在各個單元中找需要的實體(例如按照一定的半徑距離)

難點2:

一些早期的2D平面游戲,將一張地圖劃分為一個個正方形的方格,類似此類地圖,直接利用A*算法運用到其上即可得到路徑。

而一些地圖單元粒度略細,坐標范圍略廣的場景(例如許多MMO RPG),就不能如上做法了,因為如果作為一台游戲服務器,大量大范圍的尋路請求,會占用掉整個CPU資源,而導致整個服務的對外能力呈現為0。我們的解決方法是采用waypoint,在地圖上設立關鍵點,每次運算A*之前,需要find anchor,來作為A*算法的起始。

對於3D場景waypoint也將成為瓶頸,因為3D場景地形會比2D地形復雜的多,且坐標系也多了一維,意味著范圍更大,waypoint還有一個弊端是必須人工設置,且尋路所直接得到的路徑非常曲折,需要通過一定的平滑處理,3D場景一般采用NavigationMesh技術來解決這個問題,關於NavigationMesh的詳細介紹我也不多作描述,只是可以簡單地說:

它可以利用一種自動生成的算法,來自動將一張地圖劃分為一個個的凸多邊形

在凸多邊形的基礎上,尋路變得簡單,首先凸多邊形內的兩個任意點之間,都可以無障礙通行,有了這個基礎,我們的尋路可以先從凸多邊形為單位開始快速計算,得到凸多邊形節點的鏈接之後,再計算凸多邊形內部的路徑。

PS.假設你是第一次聽到NavigationMesh技術,有可能會對我以上所講無法理解,那麼請自行google,值得一提的是,假設有動態障礙的介入(例如一塊滾動的石頭),那麼就要進行實時的動態多邊形切割,而關於A*算法,已經普遍被認為是最適合的游戲地圖尋路算法了,其優化方案也有很多,也有許多盡量讓服務器盡快響應客戶端的方法(例如經典的生成三步驟:快捷路徑-完整路徑-矯正路徑),這些大家網上皆可查閱。

難點3:

一般的游戲服務器的主邏輯服務,都會按照游戲的功能來劃分,例如按照不同的地圖,當數據量達到一定的規模,這些服務器會成為瓶頸,且難以擴展。

一種理論上可行的方案是:將某一張地圖的某一塊劃分為一個抽象單位(例如上面提到的多邊形),所有邏輯服務器在運行時動態負載地圖上的這些單位。

例如以下場景:

Host A – Map A

Host B – Map B

Host A 上起先跑著Map A

Host B 上起先跑著Map B

但Map A上負載的實例(玩家)可能過多,導致Host A的負載到達瓶頸,而Map B上的負載不大,那麼此時可以進行動態調整

調整過程為:對Map A進行一些凸多邊形合並,合並之後仍是一個凸多邊形(Map Aa),將這個凸多邊形(Map Aa)的所有信息和上面的實力信息,同步到Host B,然後Host B將其進行本地合並 Map B + Map Aa = Map(B + Aa),然後兩邊的Host都需要對各自的Map進行重新切割,以保證NavigationMesh結構

這一過程需要一定的性能代價,不過是網絡上(數據同步),還是CPU計算上(重新切割合並),所以何時需要動態調整,需要仔細斟酌,需要特別說明的是,判定動態調整的進程是一個獨立的觀察者,它需要相對公平的准則來監督每一個game/map server

另一個問題是地圖邊界的處理,在地圖邊界上玩家之間的交互(交易,戰斗,等),需要將其中一個玩家的數據同步到另一個玩家所在的host進行處理,然後同步回去,這個同步過程可能會造成延時的提升,當然客戶端應該盡量進行仿真效果的處理,而不應同步等待服務響應。

對於大世界場景的游戲,或許現在已經不是主流的游戲類型,但卻一直是技術上的挑戰,也許未來,我個人興許會著手開發一個這樣的demo,來完成多年的夢想。

好了,就先胡謅到這吧,雖然按照標題的節奏,可能會有續篇,但本人也不排除只有這麼一篇的可能,畢竟只是今天一時興起的胡謅。。。

 

另外歡迎大家到我的個人博客一起討論:www.cppthinker.com

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved