Heaps — Haxe 跨平台高性能游戏引擎
待复核Heaps 是一个用 Haxe 写 2D / 3D 游戏的跨平台图形引擎,目标是让同一套游戏逻辑跑到浏览器、桌面、移动端和主机。日常类比:像一套能换插头的专业摄影灯——灯头、支架和调光逻辑不变,只是根据片场换不同电源线。
最小例子长这样:
class Main extends hxd.App { override function init() { var tf = new h2d.Text(hxd.res.DefaultFont.get(), s2d); tf.text = "Hello Heaps"; }
static function main() { new Main(); }}hxd.App 帮你开窗口、建渲染循环和准备 s2d / s3d 两个根场景;h2d.Text 把文字对象挂到 2D 场景上;new Main() 才真正启动应用。你写的是 Haxe,但输出可以是 JavaScript/WebGL,也可以是 HashLink 桌面程序。
它和 phaser、love2d 这类入门框架不同:Heaps 更像“给会写代码的游戏团队用的渲染底座”,编辑器少一点,底层控制多一点。官方展示页列出 Dead Cells、Northgard、Dune: Spice Wars 等商业游戏,说明它不是玩具 demo,而是能扛真实项目的工程工具。
不理解 Heaps,下面这些事会很难解释:
- 为什么 Haxe 游戏团队能用一套语言同时面向 WebGL、桌面、移动端和主机,而不是每个平台重写一套。
- 为什么 2D 和 3D 可以放在同一个应用里:UI、地图、角色、模型共享资源系统和主循环。
- 为什么高性能游戏引擎不一定要从 Unity / Unreal 这种大编辑器开始,代码优先路线也能做商业作品。
- 为什么 shader、资源打包、平台 target 这些“底层脏活”会直接影响游戏能不能稳定上线。
Heaps 的核心可以拆成 三件事:
-
场景根节点:
s2d是 2D 根场景,s3d是 3D 根场景。类比:同一个剧场里有平面字幕层和立体舞台层,你把对象放到哪一层,引擎就按对应规则渲染。 -
强类型资源入口:图片、字体、声音、模型放进
res/后,可以通过hxd.Res.logo.toTile()这种方式访问。类比:仓库管理员给每个素材贴好标签,拿错名字会在编译期或启动期暴露,而不是玩家点到某关才黑屏。 -
多 target 编译:README 给出的样例可以编到 JS/WebGL、HashLink、Flash,官方文档还分别讲 HTML5 和 HashLink。类比:同一份菜谱,厨房可以用电磁炉、燃气灶或烤箱,但食材清单和做法主线不变。
这三件事合起来,是 Heaps 的差异点:它不是只帮你“画出来”,还把跨平台、资源、shader 和性能优化都放到同一套 Haxe 工作流里。
案例 1:官方 Hello World,先确认渲染链路通了
Section titled “案例 1:官方 Hello World,先确认渲染链路通了”官方入门会先建 compile.hxml:
-cp src-lib heaps-js hello.js-main Main-debug再写入口:
class Main extends hxd.App { override function init() { var tf = new h2d.Text(hxd.res.DefaultFont.get(), s2d); tf.text = "Hello World"; } static function main() { new Main(); }}逐部分解释:-cp src 告诉 Haxe 源码目录;-lib heaps 引入引擎;-js hello.js 选择浏览器输出;-main Main 指入口类。代码里 init() 只在应用准备好后跑一次,适合创建首屏对象;文字挂到 s2d,说明它走 2D 渲染树。
案例 2:Base2D,把多个 sprite 挂到一个父对象
Section titled “案例 2:Base2D,把多个 sprite 挂到一个父对象”官方 Base2D 示例展示了 2D 常见写法:
override function init() { hxd.Res.initEmbed(); var obj = new h2d.Object(s2d); obj.x = Std.int(s2d.width / 2); obj.y = Std.int(s2d.height / 2);
var tile = hxd.Res.hxlogo.toTile().center(); for (i in 0...15) { var bmp = new h2d.Bitmap(tile, obj); bmp.x = Math.cos(i * Math.PI / 8) * 100; bmp.y = Math.sin(i * Math.PI / 8) * 100; bmp.alpha = 0.1; bmp.blendMode = Add; }}逐部分解释:initEmbed() 初始化内嵌资源;obj 是一组 bitmap 的父节点,移动父节点就能带着整组一起动;toTile().center() 把图片转成可绘制 tile 并把锚点移到中心;循环里 15 个 bitmap 共用同一张 tile,减少重复加载。
案例 3:Base3D,在 s3d 里放 mesh、材质和灯光
Section titled “案例 3:Base3D,在 s3d 里放 mesh、材质和灯光”官方 Base3D 示例展示了 3D 最小骨架:
override function init() { var prim = new h3d.prim.Cube(); prim.translate(-0.5, -0.5, -0.5); prim.unindex(); prim.addNormals(); prim.addUVs();
var tex = hxd.Res.hxlogo.toTexture(); var mat = h3d.mat.Material.create(tex); var cube = new h3d.scene.Mesh(prim, mat, s3d);
var light = new h3d.scene.fwd.DirLight( new h3d.Vector(0.5, 0.5, -0.5), s3d ); light.enableSpecular = true;}逐部分解释:Cube() 只给几何形状;addNormals() 让灯光知道每个面朝哪边;addUVs() 让贴图知道怎么贴上去;Material.create(tex) 把资源变成材质;Mesh(..., s3d) 才把立方体放进 3D 场景;灯光决定它不是一块平面色块。
-
忘记初始化资源系统:直接写
hxd.Res.logo.toTile()可能找不到资源;原因是hxd.Res.initEmbed()、initLocal()或自定义 loader 必须先建立资源入口。 -
把 2D 对象挂到 3D 心智里理解:
h2d.Bitmap属于s2d的显示树,不会自动参与 3D 灯光;原因是 Heaps 明确分了h2d和h3d两套渲染语义。 -
HTML5 target 忘记 canvas:只生成
game.js不够,页面里还要有canvas#webgl并加载脚本;原因是浏览器输出需要一个 WebGL 画布承接渲染。 -
HashLink 后端库选错:桌面运行要在
hxml里选择hlsdl或hldx;原因是窗口、输入和图形后端不是 Haxe 标准库自带的。
适用 vs 不适用场景
Section titled “适用 vs 不适用场景”适用:
- Haxe 团队做 2D / 3D 游戏,希望一套代码覆盖 Web、桌面、移动端和主机。
- 需要高性能渲染、shader、资源打包和自定义管线,但又不想被完整编辑器工作流绑住。
- 已经有自己的关卡编辑器、数据表、构建系统,只缺一个稳定的图形和运行时底座。
- 想学习游戏引擎底层:场景树、材质、mesh、资源 loader、WebGL / HashLink target。
不适用:
- 完全零基础、想拖拽节点和可视化拼场景,优先看 godot 或 Unity。
- 只做普通 Web 2D 小游戏,且团队主要会 JavaScript,phaser 或 pixi 更直接。
- 只想学 Lua 写小原型,love2d 的概念更少,反馈更快。
- 需要大型现成资产商店、可视化动画时间线和非程序策划深度参与,Unity / Unreal 更成熟。
历史小故事(可跳过)
Section titled “历史小故事(可跳过)”- Haxe 背景:Heaps 的作者 Nicolas Cannasse 也是 Haxe 语言的重要创建者,所以它天然围绕 Haxe 的跨平台编译能力设计。
- 商业验证:官方展示页列出 Dead Cells、Northgard、Dune: Spice Wars、Wartales 等游戏,说明 Heaps 经历过真实项目压力。
- 社区入口:GitHub 仓库约 3.6k stars,README 指向社区论坛、Discord、在线 sample 和 API 文档。
- 版本演进:仓库长期以
master为主线,官方页面仍把 HTML5、HashLink、H2D、H3D、HXSL 分成独立文档区维护。 - 生态气质:它不像 Unity 那样“编辑器先行”,更像 Shiro / Motion Twin 这类代码团队沉淀出的内部工具逐渐开放。
- Heaps 的第一直觉不是“一个游戏编辑器”,而是“Haxe 代码里的跨平台渲染运行时”。
s2d/s3d是读代码的地图:看到对象挂到哪棵树,就知道它受哪套渲染规则影响。- 资源系统是生产力核心:
hxd.Res把图片、字体、模型、声音变成有类型的入口,减少路径字符串乱飞。 - 跨平台不是免费午餐:HTML5 要 canvas 和 WebGL,HashLink 要后端库,主机还需要对应平台资格。
- 官方仓库:HeapsIO/heaps —— README 写清平台、sample 编译方式和社区入口。
- 官方文档首页:Heaps documentation —— 从 H2D、H3D、HXD、HXSL 到 target platform 的总目录。
- 官方入门:Hello World —— 最小项目结构、
compile.hxml和第一段hxd.App代码。 - 官方示例:Live samples with source code —— Base2D、Base3D、Particles、Filters、Shadows 等可运行示例。
- 官方展示:About Heaps —— 看它被哪些商业游戏和 jam 游戏用过。
- phaser —— 浏览器 2D 游戏框架,对照“完整 2D 系统”和 Heaps 的跨平台底座。
- phaser —— 同样做游戏,但 Phaser 主战场是浏览器 2D,Heaps 更强调 Haxe 跨平台和 2D/3D 并存。
- pixi —— Pixi 偏 2D WebGL 渲染库;Heaps 包含资源、3D、shader 和多 target 工作流。
- godot —— Godot 编辑器和节点系统更完整;Heaps 更代码优先,适合已有工程管线的团队。
- love2d —— 都适合代码型游戏开发,但 LÖVE 用 Lua 做轻量 2D,Heaps 用 Haxe 扛更重的跨平台渲染。
- bevy —— 都是现代游戏引擎路线;Bevy 强在 Rust ECS,Heaps 强在 Haxe target 和实战渲染管线。
- owens-2007-gpgpu-survey —— 理解 GPU 可编程渲染背景后,再看 Heaps 的 HXSL 和现代 GPU 取向会更顺。
- williams-1983-mipmap —— 贴图、采样和 mipmap 是 2D/3D 引擎共同的底层知识。
(暂无反向链接)