BlockOS開發(fā)日志(六)區(qū)塊加載
抱歉,這段時間沒空寫實現(xiàn)的總結(jié)型日志了。實現(xiàn)相關(guān)的文章后面有空的時候再來補。
對于加載、卸載的需求
只有當玩家的區(qū)塊坐標出現(xiàn)變化時,才會觸發(fā)區(qū)塊加、卸載。因此應該需要一個區(qū)塊管理器,每次更新檢查玩家的區(qū)塊坐標,然后在變動時,計算出“需要激活的區(qū)塊”列表。
接著客戶端需要讓“需要激活的區(qū)塊”列表與“當前激活的區(qū)塊”列表取補集,這個補集即需要加載的新區(qū)塊;讓“當前激活的區(qū)塊”列表與“需要激活的區(qū)塊”列表取補集,這個補集即需要卸載的舊區(qū)塊。
對于需要加載的新區(qū)塊,應該把它們做成請求列表然后發(fā)給服務器。對于要卸載的舊區(qū)塊,應該可以直接拋棄。
最后,需要一個重傳機制。每隔一段時間,就讓“需要激活的區(qū)塊”列表與“當前激活的區(qū)塊”列表取一次補集,只要補集不為空,就再次發(fā)送這個補集的請求列表。
相對獨立地,區(qū)塊管理器應該監(jiān)聽“區(qū)塊加載”事件,如果事件中的新區(qū)塊在“需要激活的區(qū)塊”列表內(nèi),那么就取出區(qū)塊信息,然后讓一個空閑的區(qū)塊對象使用這個區(qū)塊信息進行渲染。
需求分析
先看一下整個過程涉及到了哪幾個實體。首先區(qū)塊管理器是肯定的。然后是區(qū)塊管理器管理的區(qū)塊對象。最后是一個用于和服務器通信的代理。這個通信代理可以改造成一個接口,有一個RequestChunks()方法,用于提交加載區(qū)塊請求,一個OnChunkLoad委托,用于分發(fā)加載事件。排列一下,這塊也就三個實體:
區(qū)塊管理器 ChunkManager
區(qū)塊對象 Chunk
通信代理 IChunkStorage
為了實現(xiàn)不頻繁創(chuàng)建、銷毀區(qū)塊對象,需要為區(qū)塊管理器設計兩個容器。一個是“激活的區(qū)塊”列表。一個是“未激活的區(qū)塊”列表,舊區(qū)塊被卸載時,其區(qū)塊對象就會被放入這個列表,它只要能存取就行,就做成隊列吧。
然后區(qū)塊管理器需要一個更新方法,在這個方法以玩家當前位置為參數(shù)。為了判斷玩家的區(qū)塊坐標出現(xiàn)了“變動”,因此區(qū)塊管理器需要緩存玩家上次的區(qū)塊坐標,如果不同,才觸發(fā)計算“需要加載的區(qū)塊”列表的過程。這個過程中計算出兩個補集。當這兩個補集存儲的內(nèi)容不為空時,就會做出相應的請求、回收操作。
所以區(qū)塊管理器需要哪些字段呢?應該需要四個:
用于存儲“需要加載的區(qū)塊”集合與“當前加載的區(qū)塊”集合之間補集的隊列requestedChunks
用于存儲“當前加載的區(qū)塊”集合與“需要加載的區(qū)塊”集合之間補集的隊列g(shù)arbageChunks
用于存儲“當前加載的區(qū)塊”的字典chunks
用于存儲被回收的區(qū)塊的隊列inactivatedChunks
好像輪廓已經(jīng)很清晰了。那么就開干吧。