🧡Haxe reaches null0 through its HL/C target. Callbacks are closures you assign rather than exports, and there is no try/catch, but you get a mature, batteries-included language.
- Template: cart_haxe - press "Use this template" and you have a working game.
- Docker image:
ghcr.io/notnullgames/null0-cart-haxe:latest(linux/amd64 only - runs emulated on Apple Silicon) - Your code:
cart/Main.hx, compiled with haxe, HL/C + wasi-sdk - Bindings:
carts/haxe/Null0.hx(baked into the docker image for you) - WASI is available, so ordinary file and stdio calls work.
- See carts made with Haxe
- API docs for Haxe
building
You do not install haxe, HL/C + wasi-sdk - the docker image has it, and the current null0 bindings, baked in. There is nothing in your project to keep in sync with the engine.
docker run --rm --user $(id -u):$(id -g) --platform linux/amd64 \
-v ./cart:/src -v ./webroot:/out \
ghcr.io/notnullgames/null0-cart-haxe:latest mygameThe template wraps that in npm start, which also serves the result and rebuilds when you save.
Haxe notes
- Callbacks are closures you assign (
Null0.onUpdate = ...), not exports. - No
try/catch: wasm exception-handling is not available in the host interpreter.
a cart, in Haxe
This is carts/haxe/simple/Main.hx in the engine repo - the same file CI builds into the cart below, so it always compiles.
class Main {
static function main() {
Null0.onLoad = () -> {
Null0.clear(Null0.BLUE);
Null0.drawCircle(100, 100, 50, Null0.RED);
Null0.drawText(Null0.FONT_DEFAULT, "hello from Haxe", 170, 92, Null0.WHITE);
};
}
}
// other callbacks you can set in main():
//
// Null0.onUpdate = () -> {}
// Null0.onButtonDown = (button:GamepadButton, player:Int) -> {}
carts/haxe/simple/Main.hxcallbacks
A cart implements the callbacks it cares about. In Haxe they look like this:
Null0.onUpdate = () -> {}See anatomy of a cart for the full list and what each one is passed.