深度解析:Core、GDJS、Extensions、GDevelop.js 與 newIDE 五大模塊的設計與協(xié)作)
GDevelop 架構(gòu)深度解析Core、GDJS、Extensions、GDevelop.js 與 newIDE 五大模塊的設計與協(xié)作【免費下載鏈接】GDevelop Open-source, cross-platform 2D/3D/multiplayer game engine designed for everyone.項目地址: https://gitcode.com/GitHub_Trending/gd/GDevelop導讀GDevelop 是一個開源、跨平臺的 2D/3D/多人游戲引擎其代碼倉庫的頂層目錄結(jié)構(gòu)本身就是一套清晰的架構(gòu)宣言Core負責描述與操作游戲工程結(jié)構(gòu)GDJS是純 TypeScript 編寫的運行時游戲引擎Extensions提供可插拔的對象、行為與事件擴展GDevelop.js通過 Emscripten/WebIDL 把 C 世界橋接到瀏覽器newIDE則是基于 React 的圖形化編輯器。本文基于 Core/GDevelop-Architecture-Overview.md 展開結(jié)合倉庫內(nèi)真實源碼與測試幫助你理解IDE 部分與Runtime 部分的分界、事件如何被轉(zhuǎn)譯為真實代碼、三個 Extensions 文件夾為何并存以及 GDevelop.js 橋接層的工作方式——讀完即可在源碼樹中快速定位任意功能模塊。頂層目錄五張名片一條主線GDevelop 的架構(gòu)圍繞一個核心思想展開編輯器IDE與游戲引擎Runtime解耦編輯器使用所有底層庫來讀寫、校驗并導出游戲而導出的游戲只依賴運行時引擎。倉庫根目錄下五個主要目錄的分工如下目錄說明CoreGDevelop 核心庫包含實現(xiàn) IDE 與處理 GDevelop 游戲所需的通用工具全部為 C 實現(xiàn)。GDJS游戲引擎用 TypeScript 編寫基于 PixiJSWebGL驅(qū)動所有 GDevelop 游戲運行。GDevelop.jsCore、GDJS與Extensions到 JavaScriptWebAssembly的綁定層供 IDE 使用。newIDE游戲編輯器用 JavaScript React Electron PixiJS 編寫另有 web 版本。Extensions游戲引擎的擴展提供對象、行為、事件與各種新特性。主線關系是newIDE編輯器通過GDevelop.js橋接層調(diào)用Core的 C 類來操作工程結(jié)構(gòu)通過GDJS/GDJS的 C 聲明獲得導出與代碼生成能力最終產(chǎn)出包含GDJS/Runtime代碼的游戲包。先厘清兩個概念Runtime 與 IDE文檔用兩個詞區(qū)分整個倉庫中的所有代碼IDEIntegrated Development Environment指編輯器本身。瀏覽Core或GDJS的子目錄時你會看到名為IDE的文件夾里面的類與工具只對編輯器有用并非描述游戲結(jié)構(gòu)的必需品。例如 Core/GDCore/IDE 中存放的就是編輯器側(cè)的操作工具。Runtime指游戲運行期間使用的類、工具與源碼也就是常說的游戲引擎。GDJS子目錄下的Runtime文件夾就是 GDevelop 的游戲引擎本體全部由 TypeScript 編寫。擴展Extensions同樣遵循這一區(qū)分大多數(shù)擴展都包含兩部分——一個用于IDE的聲明文件JsExtension.js以及一個或多個實現(xiàn)游戲內(nèi)功能的Runtime文件例如 Runtime Object、Runtime Behavior或由動作/條件調(diào)用的工具函數(shù)。用gd::Variable理解兩層世界的隔離文檔用變量類作為最佳例證GDevelop 允許開發(fā)者在游戲中創(chuàng)建和操作變量但這一概念在倉庫中對應兩個互不相干的實現(xiàn)編輯器側(cè)的gd::Variable屬于游戲工程結(jié)構(gòu)的一部分定義在 Core/GDCore/Project/Variable.h。編輯器界面中展示的、保存到工程文件JSON里的就是這個類。游戲引擎?zhèn)鹊膅djs.Variable定義在 GDJS/Runtime/variable.ts是游戲運行時真正使用的 JavaScript 類。兩個類的關系近乎失聯(lián)編輯器gd::Variable對引擎類gdjs.Variable一無所知引擎類除了知道如何讀取默認變量寫入的 JSON 格式之外對gd::Variable也幾乎一無所知。從variable.ts源碼可以看到gdjs.Variable的構(gòu)造邏輯正是從childDataJSON 數(shù)據(jù)遞歸構(gòu)建子變量樹。文檔還指出一個命名上的小歷史遺留gdjs.Variable其實應該叫gdjs.RuntimeVariable與gdjs.RuntimeObject以及引擎中絕大多數(shù)類的命名保持一致。這種刻意隔離正是 GDevelop 架構(gòu)的精髓編輯器保存的工程結(jié)構(gòu)只是設計圖游戲運行時則是完全獨立的執(zhí)行世界兩者通過序列化JSON單向溝通。Core 內(nèi)部游戲結(jié)構(gòu)的描述與操作Core即GDCore文件夾本質(zhì)上包含描述和操作游戲結(jié)構(gòu)內(nèi)部稱為Project所需的全部內(nèi)容事件、場景Layout、對象、行為、變量等均以 C 類實現(xiàn)于 Core/GDCore/Project 目錄。從目錄清單可以直觀看到它的覆蓋面工程與場景Project.h、Layout.h、LayersContainer.h、ExternalLayout.h、ExternalEvents.h對象與行為Object.h、Behavior.h、BehaviorsContainer.h、CustomBehavior.h、EventsBasedObject.h、EventsFunctionsExtension.h變量Variable.h、VariablesContainer.h初始實例與資源InitialInstance.h、InitialInstancesContainer.h、ResourcesContainer.h。除了數(shù)據(jù)模型Core還提供操作 Project 的工具。Core/GDCore/IDE 目錄包含允許對游戲結(jié)構(gòu)執(zhí)行復雜操作的 C 類其中最典型的是 WholeProjectRefactorer——一個非常強大的工具用于在項目中重命名所有對象、在對象被刪除后自動更新事件以及執(zhí)行各種全局性的工程重構(gòu)。該目錄下還有其他工具函數(shù)例如操作項目資源的系列類ResourcesMergingHelper、ResourcesRenamer、ArbitraryResourceWorker等均可在 GDevelop.js/Bindings/Wrapper.cpp 的 include 清單中看到以及在事件中搜索的工具EventsIdentifiersFinder、EventsVariablesFinder、EventsRefactorer等。GDJS 內(nèi)部為什么這里也有 C 文件GDJS目錄下同時存在兩個世界GDJS/Runtime真正的游戲引擎全部用 TypeScript 編寫是游戲運行期間被執(zhí)行的代碼。GDJS/GDJSGDJS 的 IDE 部分即用 C 編寫的、向編輯器描述各種能力的類例如導出如何完成導出流程相關的聲明默認擴展有哪些該目錄下有SpriteExtension、AudioExtension、CommonInstructionsExtension、KeyboardExtension、MouseExtension、TimeExtension、VariablesExtension、SceneExtension等 19 組內(nèi)置擴展負責把編輯器中的動作/條件/表達式映射到具體的 TypeScript 或 C 函數(shù)如何從事件生成 JS 代碼該目錄包含EventsCodeGenerator、LayoutCodeGenerator、ObjectCodeGenerator、BehaviorCodeGenerator、EventsFunctionsExtensionCodeGenerator等核心代碼生成器。事件系統(tǒng)從空殼到真實代碼事件是一塊幾乎為空的容器在 GDevelop 中一個事件event默認情況下幾乎什么都沒有。用傳統(tǒng)編程語言類比事件相當于一個作用域/代碼塊如 C 系語言里的{ 一些代碼 }。內(nèi)置事件默認在 GDevelop Core 中定義。從目錄可見既有StandardEvent標準事件含條件與動作也有ForEachEvent、WhileEvent、RepeatEvent、GroupEvent、CommentEvent、ElseEvent、LinkEvent、AsyncEvent等控制流事件。其中StandardEvent擁有條件conditions與動作actions而條件和動作本質(zhì)上都是gd::Instruction的列表。gd::Instruction一個函數(shù)調(diào)用一個gd::Instruction只是一個類型動作或條件的名稱加若干參數(shù)。可以把它想象成編程語言中的函數(shù)調(diào)用add(2, 3)就是調(diào)用名為 add 的函數(shù)并傳入?yún)?shù) 2 和 3。條件特殊之處在于它是返回 true 或 false 的函數(shù)并且可能被用來對對象進行過濾——從而影響后續(xù)條件和動作拾取picking到的對象集合。為什么游戲運行時看不到任何 RuntimeEvent因為它們已經(jīng)不存在了。事件會被翻譯文檔中也稱轉(zhuǎn)譯或生成即 transpiled / generated成真正的編程語言代碼這個過程叫Code Generation代碼生成對 TypeScript 游戲引擎而言發(fā)生在 GDJS/GDJS/Events/CodeGeneration。也就是說編輯器中可視化編排的事件在導出時被EventsCodeGenerator等 C 類直接轉(zhuǎn)譯為GDJS/Runtime中可執(zhí)行的 JavaScript/TypeScript 邏輯運行時不再保留事件對象本身。這也是 GDevelop 事件系統(tǒng)性能與運行時純凈度的根源。三個 Extensions 文件夾為什么會有三個GDevelop 編輯器和游戲引擎的設計理念是引擎本身保持精簡幾乎不內(nèi)置任何功能通過模組 / 插件 / 模塊來按需添加能力GDevelop 稱之為Extensions擴展。倉庫中有三個 Extensions 相關目錄職責各不相同目錄職責Core/GDCore/Extensions默認內(nèi)置擴展的聲明任何游戲都可用且必須存在。雖然名為 Extensions但本質(zhì)相當于編程語言中的標準庫Standard Library。GDJS/GDJS/Extensions復用上述聲明并追加自己的聲明。主要工作是為每個動作、條件或表達式指定要調(diào)用的函數(shù)名可以是 TypeScript 函數(shù)或 C 函數(shù)。Extensions真正的模組 / 插件目錄——非必需的擴展。它們不屬于 GDCore獨立運作。文檔特別說明理論上所有擴展都可以搬到Extensions/但實踐中保留一組內(nèi)置擴展提供基礎能力更務實。GDevelop.js把 C 世界橋接給 JavaScript 編輯器GDevelop.js的一切都服務于一個目標為 IDE 建立 C 與 JavaScript 之間的橋讓編輯器完全用 JavaScript 編寫并能在瀏覽器中運行即newIDE。其技術要點Emscripten 編譯 C與編譯原生二進制不同Emscripten 產(chǎn)出的是能在瀏覽器中運行的文件本質(zhì)是 JavaScript WebAssembly。Bindings.idl是核心文件GDevelop.js/Bindings/Bindings.idl 描述了 C 中需要暴露給 JavaScript 的每一樣東西。需要強調(diào)這些暴露只服務于編輯器——游戲運行時Runtime中這一切都不存在。其余文件是橋接代碼負責 JS ? C 的雙向翻譯。這需要理解 Emscripten 生成的名為 WebIDL 的橋機制。除非你想把某個 C 類暴露給編輯器、且僅寫B(tài)indings.idl接口還不夠否則通常不需要深入這些文件——90% 的情況下在Bindings.idl中讀寫一個類的聲明即可。GDevelop.js 的底層細節(jié)所有需要參與編譯的 C 文件都被集中引入到 GDevelop.js/Bindings/Wrapper.cpp 這個巨大的頭文件清單中該文件共 984 行前 90 行即包含GDCore/Events/Builtin/*全部內(nèi)置事件、GDCore/IDE/Events/*全部事件工具、GDCore/Project/*全部工程模型以及GDCore/Extensions/Metadata/*元數(shù)據(jù)類。C 編譯由 CMake 構(gòu)建系統(tǒng)驅(qū)動依據(jù) GDevelop.js/CMakeLists.txt 決定編譯內(nèi)容。文檔作者也坦言理想情況下應有自動化手段完成這一過程那樣 GDevelop.js 文件夾甚至都不需要存在。常見疑問為什么這么多 C 與 JavaScript/TypeScript為什么用這么多 CGDevelop 最初就是用 C 編寫的。C 初學起來有些嚇人但它幾乎可以在現(xiàn)存任何機器上移植配合最新的 C 特性可以寫出相當高效、安全且可讀的代碼。Core、GDJS 的 IDE 部分以及擴展的聲明層都依賴它。為什么又用這么多 JavaScript/TypeScriptJavaScript配合最新語言提案能力很強、編寫快速且有類型保障現(xiàn)代瀏覽器 JIT 特性使性能不斷提升用于 GDevelop IDE 的前端框架 React 支持非常快速、模塊化的界面開發(fā)Web 是跨平臺以及跨形態(tài)應用無可比擬的發(fā)布目標。更宏觀地看隨著 WebGL 與 WebAssembly 的興起Web 也是游戲發(fā)布的絕佳目標——同時 GDevelop 也保持模塊化以便未來為導出游戲適配更新的平臺。總結(jié)一張地圖定位整個倉庫把全文濃縮成一張尋路地圖想看工程結(jié)構(gòu)模型去 Core/GDCore/Project想看編輯器側(cè)的重構(gòu)/搜索工具去 Core/GDCore/IDE想看事件如何變成代碼去 GDJS/GDJS/Events/CodeGeneration想看游戲真正跑起來的邏輯去 GDJS/Runtime想看可插拔新特性怎么聲明去 Extensions/ExampleJsExtension想看C 如何暴露給 JS 編輯器去 GDevelop.js/Bindings/Bindings.idl。理解了 IDE 部分與 Runtime 部分這條分界線GDevelop 的每一行代碼都會各歸其位。【免費下載鏈接】GDevelop Open-source, cross-platform 2D/3D/multiplayer game engine designed for everyone.項目地址: https://gitcode.com/GitHub_Trending/gd/GDevelop創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考