Blender 新歡 Armory3D - Khamake & Khafile.js

繼?Armory Traits?介紹完混入式編程的?5 種類型后,Armory 游戲編程方面基本上算是一只腳跨進大門了,接下來還有更多的內(nèi)容等著探索。下沉到 Haxe 語言的系統(tǒng),橫著的是 Blender 場景設計與模型打造,甚至是 Armory3D 本身也有許多模塊需要深入研究。本文著重介紹其中的 Kha 構(gòu)建腳本的一些常識。以下 5 種 Armory Traits 擴展將伴隨所有的 Armory 游戲項目的開發(fā)過程:
1. **haXe** 腳本代碼文件;
2. **Nodes** 使用 Logic Node Editor 可視化編程工具定義的節(jié)點樹;
3. **UI** - User Interface (Canvas trait),使用 Armory2D 用戶界面編輯進行可視化編輯;
4. **Bundled** Armory Engine 預定義 Haxe 腳本,是 `Trait` 類型的擴展;
5. **Wasm** 使用 WebAssembly 字節(jié)碼程序;
# ? 源文檔 https://github.com/Jeangowhy/opendocs/blob/main/Haxe.md
?? Khamake & khafile.js
* [khafile.js](https://github.com/Kode/Kha/wiki/khafile.js)
* [Third Party Libraries|Libraries](https://github.com/Kode/Kha/wiki/Third-Party-Libraries|Libraries)
* [System Defines](https://github.com/Kode/Kha/wiki/System-Defines)
* [Profiling](https://github.com/Kode/Kha/wiki/Profiling)
* [Managing Your Assets](https://github.com/Kode/Kha/wiki/Managing-Your-Assets)
Kha 是一套 API 或稱為一個開發(fā)庫,它使用的構(gòu)建工具稱為 **khamake**,以及一個著色器交叉編譯器 **Krafix**,使其能夠支持多個圖形 API。支持平臺包含:Web, Mobile, Desktop, and Consoles,使用 OpenGL, WebGL, DirectX, Vulcan, 以及 Metal 等圖形 APIs。
Kha 編譯得到目標程序程序是 targets,最典型就是 C++ ( with Kore ), Krom, Web, 和 HashLink (HL)。
Blender 中執(zhí)行 Armory3D 構(gòu)建時,引擎插件會將所有資源、著色器、紋理等等都存放在 compiled 目錄下,最后打包到輸出目錄,主要是 krom 和 krom-resources 兩個目錄。構(gòu)建腳本 khafile.js 也自動生成。而手動執(zhí)行 Kha 構(gòu)建時,就需要自動處理,包括配置 khafile.js 腳本,當然可以調(diào)用 khamake 生成。為了方便調(diào)用 Khamake,可以創(chuàng)建一個 kmake.bat 批處理文件:
? ? # Kha init
????node.exe C:\HaxeToolkit\armsdk\Kha\make --init
????# kmake.bat
? ? node.exe C:\HaxeToolkit\armsdk\Kha\make %*
以下是 Armory 插件運行時的基本操作,操作包括:
1. 導出內(nèi)嵌在 .blend 內(nèi)部的資源文件;
2. 調(diào)用 cmft - cubemap filtering tool 生成紋理圖像 LOD 分級細節(jié)貼圖;
3. 期間會在 compiled\Assets 和 Shaders 目錄下生成各種默認配置的資源、著色器程序;
Armory 運行時會自動生成 khafile.js 構(gòu)建腳本,腳本中使用到的對象類型定義在 Kha 源代碼中。就腳本中的 `Project` 對象來自源代碼:
? ? armsdk\Kha\Tools\khamake\src\Project.ts
各個方法說明如下:
使用 `Project()` 方法注冊一個工程標識,格式為:name_version。
使用 `addLibrary("/armsdk/armory")` 等等引入模塊。
使用 `addAssets()` 方法添加資源引用。
使用 `addParameter()` 給 Haxe 添加編譯參數(shù)設置,比如 addParameter('-main Main')。
使用 `addDefine('arm_physics')` 添加符號定義來啟用相應模塊或者條件編譯,這里添加物理引擎模塊。
所有 `rp_` 前綴的符號定義基本都與 Render Path 功能相關。
其中 `js-es` 符號用來指定轉(zhuǎn)譯得到的 ECMAScript,即 JavsScript 版本號。
使用 `resolve(project)` 替換舊版本 Kha 腳本的 return 方式。
模塊默認位于 Libraries 目錄,project.localLibraryPath 屬性可以指定模塊目錄。
構(gòu)建腳本中經(jīng)常使用 `addParameter()` 告訴 Haxe 編譯時調(diào)用 macro 函數(shù)。Haxe 初始化宏是一種在命令行中調(diào)用宏的方式,[Initialization Macros] 命令行格式 `--macro callExpr(args)`。它用來向編譯器注冊一個函數(shù),使其在宏上下文創(chuàng)建后得到調(diào)用,比如,keep() 就是一個宏初始化調(diào)用。宏初始化必需在 `--main` 參數(shù)之前指定。
如果 `--macro` 調(diào)用的是一個 plain identifier,就會在 Haxe Standard Library 中的`haxe.macro.Compiler` 內(nèi)定位這個標識,這里定義多個非常有用的初始化宏:
? ? haxe\std\haxe\macro\Compiler.hx
比如,`include` 初始化宏在編譯時用來引入整個包,可以遞歸地處理引入,當然也可以自定義宏:
? ? --macro include('some.pack', true)
? ? --macro some.Class.theMacro(args)
由于所有宏共享相同的 [Macro Context],初始化宏可以設置其他宏用作配置的靜態(tài)字段的值。
1. `Compiler.include` Includes all modules in package `pack` in the compilation.
2. `Compiler.keep` Marks types or packages to be kept by DCE (Dead Code Elimination).
官方提供的 Armory Examples Browser 項目就是一個 Haxe Web 應用,配置中就調(diào)用了自定義宏。當然,Haxe 開發(fā) Web 應用,體驗上遠不及 React/Vue/Angular 等更現(xiàn)代的組件式 Web 開發(fā)框架。Haxe 提供的 js 模塊設計上相當于 jQuery 時代的水平,需要調(diào)用 Document API 構(gòu)建 HTML。https://github.com/armory3d/armory_examples_browser
BG-36's Tutorials - SaveLoadMechanism 教程演示了 Haxe 代碼如何與 UI 交互。
https://github.com/BlackGoku36/armory-tutorial-download/tree/master/SaveLoadMechanism
Kha 構(gòu)建 HTML5 或 Flash 應用時,如果有 .wav 等等資源文件,就需要指定 ffmpeg 工具來轉(zhuǎn)換格式。聲波文件在 HTML5 平臺中需要轉(zhuǎn)換為 .ogg 文件,在 Flash 平臺中轉(zhuǎn)換為 .mp3 文件,優(yōu)化文件大小。
? ? node Kha/make html5 --ffmpeg "/path/to/ffmpeg.exe"
khamake 期待的資源文件格式如下,其它格式資源通過 Assets.blobs 作為 Blob 對象訪問:
01. **images**: png, jpg, hdr
02. **sounds**: wav (sample rate: 44100Hz 16 bit)
03. **videos**: mp4
04. **fonts**: ttf
資源一般使用 assets 目錄,但不強制使用此目錄,可以使用多個資源目錄。
假設 assets 資源目錄包含文件如下:
在構(gòu)建腳本中添加引用后,就可以通過 `Assets.types.nameOfAsset` 這樣的語法來讀取資源到內(nèi)存中。比如,讀取以上的圖像資源就是 kha.Assets.images.map1_tiles 或者 map2_tiles,目錄使用下劃線分隔。已經(jīng)有對應分類的資源就可以相應的分類訪問,無分類的資源就作為大二進制數(shù)據(jù)對象 `Assets.blobs`。
但是注意,數(shù)據(jù)文件經(jīng)過處理后,目錄結(jié)構(gòu)被碾平,假設以上兩個目錄中在同同名兩個文件,如 a.dat,那么 kha.Assets.blobs.a_dat 只能訪問到其中一個數(shù)據(jù)文件,為了解決這個問題,Kha 提供了路徑映射,生成的代碼保持目錄結(jié)構(gòu),以訪問 map1_a_dat 和 map2_a_dat 兩個數(shù)據(jù)資源:
不要創(chuàng)建名稱為 Haxe 關鍵字的文件,如 default.png 就不好,應該用 `_default.png` 這樣的名稱。因為在 Assets 中顯示的資源名稱是使用輸出資源目錄的 macro 和 json 文件導入的,所有資源命名必須符合變量、函數(shù)的命名規(guī)則。資源導出目標為 `<build target>-resources`,比如 Krom 導出方式,資源目錄就是 krom-resources 目錄。
構(gòu)建腳本 khafile.js 中的其它配置參考:
