Haxe targets JavaScript natively, so any Haxe program that renders to a <canvas> runs on Wavedash. No runtime is shipped alongside your game — the compiler emits a single .js file you load from a static HTML shell.
Build for web
Write a build.hxml that emits JavaScript:
-cp src
-main Main
-js build/main.js
-D js-es=6
-D no-traces
Then run haxe build.hxml. The compiler writes build/main.js. Commit a matching build/index.html that includes it:
<!doctype html>
<html>
<head><meta charset="utf-8" /><title>My Haxe Game</title></head>
<body>
<canvas id="gameCanvas"></canvas>
<script src="./main.js"></script>
</body>
</html>
SDK integration
Call the JavaScript SDK from Haxe with js.Syntax.code. Wavedash injects Wavedash as a global before your script runs.
Calling Wavedash.init() is required. Your game stays hidden behind the Wavedash loading screen until you do. Call it once your game is ready to play.
import js.Browser;
class Main {
static function main() {
Browser.window.addEventListener("load", onLoad);
}
static function onLoad(_) {
// set up your canvas, game loop, input handlers, etc.
// Signal load-complete and initialize the SDK
js.Syntax.code("Wavedash.updateLoadProgressZeroToOne(1.0)");
js.Syntax.code("Wavedash.init({ debug: true })");
Browser.window.requestAnimationFrame(loop);
}
}
For anything more than a one-off call, wrap the SDK in a Haxe extern so the compiler can type-check your usage:
@:native("Wavedash")
extern class Wavedash {
static function init(config: Dynamic): Bool;
static function updateLoadProgressZeroToOne(progress: Float): Void;
static function uploadLeaderboardScore(id: String, score: Int, keepBest: Bool): js.lib.Promise<Dynamic>;
// ...add more as you need them
}
wavedash.toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./build"
entrypoint = "index.html"
The example repo commits both build/index.html and a prebuilt build/main.js so you can run wavedash dev without a Haxe toolchain on hand.