提煉游戲引擎系列:初步設計引擎
前言
本文為后續引擎提煉定下了一個大致的方向,沒有給出完整的引擎架構。這就夠了!讓我們在具體開發過程中再來從底向上設計吧!
本文目的
1、進行引擎提煉的前期規劃,明確引擎提煉的整體流程和引擎的非功能性需求。
2、從炸彈人領域模型中提煉出精簡的領域模型,作為炸彈人的參考模型。
3、從炸彈人參考模型中提煉出抽象的領域模型,作為引擎的初步領域模型。
本文主要內容
前期規劃
開發流程
引擎提煉的整個流程如下圖所示:

說明
? 回顧炸彈人游戲
介紹炸彈人游戲的基本情況,回顧炸彈人游戲的設計
? 初步設計引擎
給出引擎的初步設計,從炸彈人領域模型中提煉出一個精簡的領域模型,作為炸彈人的參考模型,再從中提煉出一個抽象的領域模型,作為引擎的初步領域模型
? 第一次迭代
參考引擎的初步領域模型,從炸彈人參考模型中提煉出對應的通用類和基礎的引擎框架,使引擎具備游戲入口、預加載、主循環、層、精靈、動畫、事件管理等基本功能,并將炸彈人游戲改造為基于引擎實現,通過測試。
? 第二次迭代
進一步提煉炸彈人類和引擎類,提煉通用模式,消除引擎中的用戶邏輯,進行引擎的整體梳理和修改,對應修改炸彈人游戲,通過測試。
本文進行“回顧炸彈人游戲”和“初步設計引擎”這兩個步驟。
引擎非功能性需求
1、可測試性
引擎是一個可復用的組件,應該保證正確和可測試。
方案:編寫全覆蓋引擎的單元測試。
炸彈人游戲有完整的單元測試,可以將其修改為引擎的單元測試。
注:本系列不會討論測試。
2、可擴展性
本系列提煉的引擎還不完善,后續會加入更多的功能,因此引擎需要具有靈活的架構,滿足開閉原則,方便以后的擴展。
引擎應該支持插件化開發,獨立功能的模塊可以作為通用插件從引擎中獨立出去,由用戶選擇是否引入到引擎中。
方案:基于高內聚低耦合的總體思想,使用面向對象思想,復用炸彈人游戲中可擴展性的模塊,從中提煉引擎,保持良好的引擎架構。
3、可讀性
引擎應該具備良好的可讀性,易于后續開發時理解之前的設計,方便他人理解引擎的實現。
方案:
(1)保持代碼整潔
(2)只保留必要的注釋
(3)編寫必要的文檔
(4)通過良好的命名和測試用例來輔助讀者理解代碼
(5)代碼風格應該統一
回顧炸彈人設計
本節會介紹炸彈人游戲的基本情況,讓大家有個整體印象。
炸彈人系列博文
炸彈人源碼下載
炸彈人外部依賴
在炸彈人游戲中,我使用了以下的庫:
第三方庫
? jQuery
使用它的選擇器,進行dom操作。
? progressBar
這是一個jQuery的進度條插件,我用它來顯示預加載圖片的進度。
? jasmine
這是一個測試框架,使用它可以進行Javascript單元測試。
我的庫
? YOOP(命名空間:YYC.Class、YYC.AClass、YYC.Interface)
這是我的Javascript的oop框架。具體可參見發布我的Javascript OOP框架YOOP。
? 圖片預加載控件PreLoadImg(命名空間:YYC.Control)
? 工具庫YTool(命名空間:YYC.Tool)
我的工具方法庫。
? jsExtend
Javascript原生對象擴展,對js的String和Array對象進行了擴展。
? 模式庫(命名空間:YYC.Pattern)
包括創建對象模式的命名空間方法namespace和觀察者模式的Observer.js
炸彈人的概念層次結構

炸彈人領域模型
炸彈人游戲的領域模型如下圖所示:

查看大圖
初步設計引擎
本節提出了我在實踐過程中總結的引擎設計原則,以及炸彈人的參考模型和引擎的初步領域模型,為后面的引擎提煉打下了基礎。
引擎設計原則
1、引擎不應該依賴用戶,用戶應該依賴引擎

引擎應該保持通用性,不應該包含用戶邏輯。
2、盡量減少引擎依賴的外部文件
因為:
(1)增加引擎的不穩定性
依賴的外部文件變化時,引擎也需要對應修改。
(2)外部文件不一定完全適合引擎
外部文件不是基于引擎開發的,可能需要對其進行改造,從而適合引擎的需要。但是由于外部文件不穩定或者對外部文件實現不了解等原因,想要針對引擎的具體情況進行改造比較困難。
(3)加大用戶負擔
引擎可能只需要使用外部文件的一小部分,但是卻需要引入整個外部文件,這會增加引擎的整個文件大小,加大用戶負擔。
所以:
(1)如果必須要依賴,也盡量依賴自己開發的庫,而不要依賴第三庫。
(2)第三方庫可以作為插件引入到引擎中,由用戶自行選擇。
(3)可考慮將第三方庫改造為引擎的內部庫。
a.如果引擎依賴的是自己開發的、沒有發布的庫,則可以直接引入,作為引擎的內部庫
因為自己開發的、獨立發布的庫需要獨立變化,不應該與引擎綁到一起。
b.如果引擎只依賴第三方庫的部分內容,則可將依賴的第三方庫的最小集提取為引擎的內部庫。
3、引擎應該具有很好的可擴展性
這里可擴展性包括兩個方面:引擎可擴展性和用戶可擴展性。
(1)引擎可擴展性
在前面的非功能性需求中已經說過了,引擎應該具有靈活的架構,方便以后的擴展。
(2)用戶可擴展性
用戶可擴展性指用戶可以插入自己的邏輯到引擎中,實現引擎的變化點。
4、盡量減少用戶負擔
引擎應該實現底層邏輯,用戶只負責實現業務邏輯。
引擎應該盡量封裝高層API,提供給用戶使用,減少用戶的工作量。
代碼組織方式
文件組織方式一般有兩種:
1、使用js模塊加載器(如sea.js)。在沙箱環境中,將需要引用的文件加載進來,然后通過局部變量名來使用。
2、使用命名空間。
因為:
(1)引擎文件數量不是很多,還不需要用模塊加載器。
(2)如果使用模塊加載器,則引擎必須依賴模塊加載器,用戶使用引擎時也必須按照模塊加載器的方式來引用引擎文件,這樣會增加復雜度,加大用戶負擔。
所以引擎采用命名空間的方式來組織文件,引擎的頂級命名空間為YE。
引擎名
該引擎命名為YEngine2D。
代碼結構
炸彈人和引擎代碼結構如下圖所示:

- Content
炸彈人游戲的資源文件- Image
圖片資源文件
- Image
- Scripts
js文件- bomber
炸彈人js文件 - myTool
工具- frame
框架文件 - pattern
模式文件 - tool
工具文件
- frame
- plugin
外部插件 - yEngine2D
引擎文件
- bomber
- Views
頁面
思考
1、炸彈人改造為基于引擎實現后,是否需要通過炸彈人的單元測試?
因為:
(1)在提煉引擎的過程中,引擎變動頻繁,引擎變動會導致使用引擎的炸彈人變動,對應的炸彈人單元測試也會可能跟著變動。這樣就需要經常修改單元測試,工作量太大。
(2)我不會二次開發炸彈人游戲,不需要維護炸彈人的單元測試。
(3)本系列的重點是提煉引擎,應該把精力都集中在引擎上。
綜上所述,只對引擎進行單元測試,而不再維護炸彈人的單元測試,改為直接通過瀏覽器運行炸彈人游戲來進行運行測試。
2、引擎應該是通用的,還是只針對“炸彈人游戲”所屬的RPG類型?
因為提煉引擎的目的是為了更快地開發游戲,不僅僅只有RPG類型,也包括其它類型的游戲,所以應該提出一個通用的引擎。
然而本系列并不能提出一個完全通用的引擎,因為我是從炸彈人游戲中提煉引擎的,該引擎只能保證適應炸彈人這種RPG類型的游戲。提煉通用引擎是一個長期任務,目前我只能在提煉引擎時盡可能地消除炸彈人游戲的用戶邏輯,提高通用性。在以后的實踐中,需要將該引擎盡可能多地應用到不同類型的游戲中,這樣才能最終得到一個通用的游戲引擎。
領域模型分析
炸彈人參考模型
對炸彈人的領域模型進行精簡,去掉具體的實現類,只保留必要的、能體現整個概念層次結構的和游戲框架的類:

精簡后的領域模型即為本系列的炸彈人參考模型。
引擎初步領域模型
對炸彈人參考模型進行抽象,提出抽象角色類(一個角色類可代表多個具體類,如DataOperate類,在炸彈人游戲中代表了MapDataOperate、GetPath等類),作為引擎的初步領域模型。

-
Config
全局配置類,存放游戲中的常量、枚舉值、配置信息。 -
LoadResource
加載資源的類,負責加載各種資源 -
Main
入口類,是整個系統的入口,負責啟動游戲,頁面只與該類耦合,該類是整個系統的入口。 -
Director
游戲主邏輯類,負責游戲的統一調度。
為什么命名不沿用炸彈人的“Game”?
因為“Game”這個名字范圍太大,不能突出“統一調度”的職責,因此命名為“Director”更為合適
- Scene
場景類,為集合類,從炸彈人的LayerManager抽象而來,負責管理場景。
在炸彈人游戲開發中,我從“如何統一調度各個層”的邏輯出發,提出了層管理類LayerManager。
現在可以進一步抽象,提出“場景”這個概念,游戲中可能包含多個場景(至少一個),場景類Scene與“場景”是1對1的關系,Scene不僅負責統一調度場景內各個層,還應該包含與場景的相關的屬性和方法。
-
Hash
具有哈希結構的集合類。 -
Layer
層類,為集合類,負責層內精靈的統一管理。
該類對應“分層渲染”的概念,一個Layer對應一個畫布canvas。
-
Collection
具有線性結構的集合類。 -
Sprite
精靈類。
每一個單獨的個體都是一個精靈類。如玩家、敵人、炸彈等,與該個體密切相關的屬性和方法都放到該類中。 -
AI
人工智能類,負責實現人工智能算法,具體可以包括尋路算法、敵人的移動模式和行為設置等。 -
Factory
工廠類,負責創建類的實例,封裝類的創建邏輯。 -
Animation
幀動畫控制類,負責控制幀動畫的播放。 -
DataOperator
數據操作類,負責對數據進行讀、寫操作。 -
Data
數據類,保存游戲數據 -
EventManager
事件管理類,負責事件的監聽和移除。
最新的引擎版本
有興趣的話您可以看下最新的引擎版本(這個不是本系列博文提出的引擎版本,而是最新修改后的引擎版本):
發布HTML5 2D游戲引擎YEngine2D
浙公網安備 33010602011771號