Tile Based Engine的設計 - 精靈鏈表
通常說來, 第三人稱 2D 游戲中通常把景物和精靈分開處理 (至少我是這樣的) 尤其是游戲機上, 硬件對精靈有支持. 現在我們的顯卡多也支持顯存間的 keycolor 檢查 Blt 操作, 實際就是用來加快精靈處理的 (也包括景物)
精靈在運動時, 往往是基于像素的 (雖然有人喜歡簡化設計, 精靈在停止的時候仍舊是站在格子里) 而景物卻是靜止在格子中.
如果能使用更有針對性的方法分別繪制, 將可以提高游戲的速度. 本文的觀點源于云風早前所寫的斜視角圖形引擎的設計系列.
并在近期實踐(制作一商業A.RPG游戲)中得到完善.
實際上, 游戲中每幀圖象, 沒有必要每次用各個圖素合成,
尤其在使用了大量如Alpha輪廓, 透明等大運算操作的情況下, 屏幕上并未更改的區域重復被運算非常的浪費時間. 所以我們可以借鑒游戲機的做法,
場景圖面創建的稍稍比屏幕大一圈, 只在屏幕移出窗口時再補繪場景, 把精靈提出, 每幀重繪于場景上.
合成精靈與場景有三大問
題, 一是如何處理精靈的遮擋問題, Isometric Tile Engine 的遮擋處理一文闡述了云風的觀點; 其二是如何清除上一幀的精靈:
(當然這一步也可以省略, 改為將場景層和精靈層合成到第三緩沖區) 如果不想多建立一屏幕后臺緩沖區, 減少合成圖層時的數據移動量,
我們可以采取在繪制精靈前保存精靈原處的場景圖象. 具體實施方案在后面將有詳細解說。
最后一大要點是以正確的次序繪制精靈了. 這里我想使用一個鏈表, 串起場景中的所有精靈, 姑且將它稱為精靈鏈表吧. 同時我們還需要另一個鏈表保存屏幕上可見的精靈, 減少我們處理精靈的數量.
場景精靈鏈表是創建場景時創建的, 在某精靈消失(死亡)后從鏈表中刪除, 精靈也可以在游戲時被創建加入鏈表.
而屏幕精靈鏈表卻是繪制屏幕時動態生成, 保證其中精靈滿足從后到前的順序. 這樣我們只需要在產生鏈表后, 依鏈表次序將精靈繪制到屏幕就可以了
:-)
那么整個處理過程如下:
根據當前的屏幕精靈鏈表清除上幀圖象中所有的精靈 清除當前屏幕精靈鏈表 遍歷整個場景精靈鏈表, 處理每個精靈的動作和狀態, 如果精靈正在屏幕上, 就將其按前后次序插入屏幕精靈鏈表. 將即將繪制的精靈位置的場景保存 按屏幕精靈鏈表次序繪制精靈到屏幕 顯示一幀圖象 循環這些步驟
第一步清除上幀精靈的具體操作中, 我們可以為每一個精靈分配一個緩存圖, 保存繪制前的場景. 但這樣比較浪費.
因為不在屏幕上的精靈根本用不著這個緩存圖. 所以我們可以進一步優化為, 精靈進入屏幕時才分配緩存圖, 移出屏幕就釋放掉.
不過內存分配實際是一個很消耗時間的過程. 當精靈大小都類似時,進一步的優化方案是限定屏幕上可以同時出現的精靈的數量,
初始化時就統一分配一批等大的緩存圖(我稱其為緩存池), 其每一個都足已容納最大的精靈. 當某個屏幕精靈需要緩存圖時,
就從緩存池中找一個沒有使用的供其使用, 精靈移出屏幕后, 放棄對緩存圖的控制即可.
關于第3步將存在于屏幕的精靈插入屏幕精靈鏈表的操作, 涉及如何判定精靈的前后關系. 我們可以在作圖時, 就將精靈的重心定為其參考點保存中圖素的文件中. 利用這個參考點的坐標就可以完成精靈的前后判定了 ;-)
本文總結了云風近期制作游戲中的些經驗, 希望對后來者有所借鑒. 成文倉促, 錯誤在所難免. 提及方法也是我的個人觀點, 游戲設計的魅力在于其設計時可以不遵循常例,任意發揮, 在此歡迎大家一起探討, 指出錯誤和不足.
|