遊戲系統開發筆記(八) 場景物件管理

2021-09-06 11:16:53 字數 2528 閱讀 9012

遊戲中,我們常常需要把整個遊戲世界中零散的角色按照一定方式組織到一起,使它們...額...發生關係。有很多與之相關的許多問題或許會遇到:我這個技能最遠攻擊距離是多少?範圍有多大?這個怪物離我多近的時候會主動攻擊我?有些地形我是否可以通過?以什麼樣的方式通過??十分接近怪物的時候我是會被撞到停下,還是從中穿過?等等等等,諸如此類。

簡單介紹下tilemap。

邏輯上乙個tilemap物件通常表示乙個具體的地圖,包括地圖名稱、編號、大小、座標表示、障礙資訊等。

因為2d遊戲的活動空間只在乙個平面上,所以tilemap的座標表示通常採用乙個二維矩陣。然後因為眾所周知的,計算機的狀態表達能力是有限的(資源是一方面,要模擬現實世界資訊必須經過ad轉換也必然損失資訊),所以這裡每個矩陣單元一定是具有一定大小的,而且出於資源效率考慮,tilemap需要給這個資料結構定義座標精度,即乙個矩陣單元代表多少實際畫素大小。

障礙資訊通常是乙個座標集合,遊戲啟動時轉換為各個矩陣單元上的障礙狀態。

但是,地圖產生只能解決座標的問題,還有許多諸如視野、攻擊範圍之類的問題解決不了。而且tilemap作為乙個概念上較為純粹的「地圖」,把其它功能也堆進去的話就不那麼合適了。而且...嗯...我覺得許多模組要頻繁的和tilemap這種小嘍囉打交道多少讓人覺得有點不放心。

所以這時候「場景(scene)」來拯救地球了。

比起map,scene在概念上更加適合解決上面提到的這些問題,比方說,「把乙個角色加入到場景中」聽起來肯定比「把乙個角色放到地圖裡更好」。上面絮絮叨叨了這麼多,scene要做哪些事情也大致上有線索了:

1、乙個場景要有一張地圖

2、場景要負責物件管理

3、場景要表示位置關係(aoi)

簡單的說,就是包裝了map,增加了物件管理功能,同時產生一些場景事件(如位置關係變化、物件轉移等)以及對外提供位置關係查詢等功能。

第一點在介紹了tilemap之後我想沒必要細說了。

第二點說明了場景物件也是要介入角色物件生命週期管理的,建立乙個有效角色之後需要將它插入到場景,而刪除之前需要先從場景拿掉,特別的,主動刪除場景的時候需要對正在交由該場景管理的物件進行操作(刪除或是轉移)。

另一種物件和場景關聯的方案是把場景層物件和邏輯層物件徹底隔離,場景層物件以指標的方式掛到邏輯物件上。這樣的話,實現上面這個建立流程的話就變成,先構建場景層物件,之後把這個物件拿給邏輯層物件進行構造(當然,也可以構建完之後塞給它)。而產生場景事件要求對邏輯物件進行操作的話,通常需要藉由乙個handler物件來完成(比如,場景層實現isceneobjhandler並提供相應操作函式,場景物件實現方法gethandler()和sethandler(...),然後邏輯層繼承一下isceneobjhandler實現其具體操作後sethandler,以此達到解耦的目的)。

這種做法比前者實現起來和概念上都繞一些,但好處的話,比如說要把角色物件做成物件池的形式,那麼就可以節約構建場景物件那部分的開銷,也使得場景層管理物件時靈活一點。

第三點的可見關係是場景物件管理中可能需要密集計算的地方,試想,場景中每個角色每次改變位置的時候可見關係都可能發生改變,而由此產生的關係改變事件又需要一一被處理,除此之外,網遊的話位置變化還需要對客戶端進行廣播。再,如果一台計算機同時開放多個常見,每個場景大量角色在移動...

下面我們把鏡頭對準場景中的某個npc,那麼它往前走那麼一小步,程式上需要做多少事呢?

首先是物件改變座標,然後是通知其它物件自己的位置已改變,這時其它物件各自判斷和該物件的這種位置關係是否需要處理,是則轉入相應處理流程。改變座標的流程不解釋,通知才是重頭戲。

有那麼幾種處理aoi問題的方法,下面簡單介紹:

其二是早期勞動人民比較慣用的做法——切豆腐,即事先把地圖區域劃分成一定大小的等大小網格(一般至少要能覆蓋可見範圍那麼大),物件移動時只通知本網格和幾個相鄰網格的所有物件(可以想象成訊號塔)。多了些維護網格的**,但絕對行之有效,對於大場景多角色的情況優化較明顯,實現起來也不困難。缺點的話,主要是視野關係不夠靈活,還是多了不少冗餘位置判斷(尤其是小視野物件多的情況),而且跨網格移動要瞬時做大量操作(卡幀的隱患)。

其三是十字鍊錶法,即以x和y兩條有序鍊錶來維護場景物件,位置變化時只需要交換節點位置(可能交換),然後往前後遍歷查詢需要通知的物件,因為鍊錶有序,所以超出視野就立即結束遍歷。這種方案省去了第二點網格隨場景變大而節點越來越多的固定開銷,而且也不會有跨網格移動需要大量操作的問題,處理起來相當靈活,在一些人眼裡甚至是最具運算效率的方法(這個本人沒有驗證過,沒有自己的結論)。

其假設所有物件具有相同大小視野的版本實現起來尚且簡單,但若每個物件可能具有不同視野的情況實現起來就略複雜了,而且目測效率大幅度降低。由於涉及到點和線段重疊關係統計,我覺得考慮使用線段樹來取代十字鍊錶,這樣一來就是x、y各有一棵線段樹,排序方面應該會優於鍊錶但是因為二叉樹前後遍歷沒線性結構那麼快,所以這個效率具體來說還是和操作的種類和頻率有關的。

具體實現就不先展開了,這裡有十字鍊錶aoi的一些額外資料:

還有一種方法是使用四叉樹來管理場景空間,思路上有點類似把第三點中的線段樹部分把x、y軸合併之後直接以二維方式來處理問題,具體不展開,有興趣的自己試試。和第三點的效率比較待測。

最後是眾多場景通常還需要乙個場景物件(這裡只場景本身)管理器,用於集中控制各個場景的生命週期,考慮做成乙個singleton吧。

遊戲系統開發筆記(八) 場景物件管理

遊戲系統開發筆記 七 物件系統設計 簡單介紹了下物件系統的設計,繼續考慮遊戲開發所需要完成的工作會發現還少乙個很重要的點 物件的活動場所。遊戲中,我們常常需要把整個遊戲世界中零散的角色按照一定方式組織到一起,使它們.額.發生關係。有很多與之相關的許多問題或許會遇到 我這個技能最遠攻擊距離是多少?範圍...

遊戲系統開發筆記(七) 物件系統設計

物件系統顧名思義自然是指oo中的程式物件了,oo程式設計中除了少部分以演算法為主的程式設計,多數時間我們的工作都在圍繞各個物件的生命週期進行著。因為遊戲中所使用到的物件較多,物件間的關係也頗為複雜,自需要一套概念上的 系統 來描述其設計及其背後所涉思想。這就是這裡提到的 物件系統 了。個人認為遊戲程...

30天自製作業系統開發筆記 記憶體管理

這本書開發的作業系統,用到了下面的記憶體分布圖 0x00000000 0x000fffff 啟動中多次使用,存放vram等內容 1mb 0x00100000 0x00267fff 用於儲存軟盤的內容。1440kb 0x00268000 0x0026f7ff 空 30kb 0x0026f800 0x0...