Rust compiles to WebAssembly via the wasm32-unknown-unknown target. The output is a .wasm binary loaded by a hand-written JavaScript entrypoint (web/game.js).
Setup
Install the WASM target:
rustup target add wasm32-unknown-unknown
Your crate should be a cdylib:
[lib]
crate-type = ["cdylib"]
SDK integration
Declare the two Wavedash SDK functions as extern imports. Wavedash injects WavedashJS into the page, and web/game.js bridges them into the WASM env namespace:
// src/lib.rs
unsafe extern "C" {
fn wavedash_init();
fn wavedash_update_progress(p: f32);
}
#[unsafe(no_mangle)]
pub extern "C" fn wd_init(width: f32, height: f32) {
// ... game setup ...
unsafe {
wavedash_update_progress(1.0);
wavedash_init();
}
}
Call wavedash_update_progress(...) with intermediate values during async asset loading. wavedash_init() automatically signals load completion, so call it last.
On the host side, web/game.js provides the implementations:
const sdk = await window.WavedashJS;
const imports = {
env: {
wavedash_init() { sdk.init({ debug: true }); },
wavedash_update_progress(p) { sdk.updateLoadProgressZeroToOne(p); },
// ...your other imports (draw primitives, score updates, etc.)...
}
};
const response = await fetch("./game.wasm");
const bytes = await response.arrayBuffer();
const result = await WebAssembly.instantiate(bytes, imports);
Build script
#!/usr/bin/env sh
set -eu
cargo build --lib --target wasm32-unknown-unknown --release
mkdir -p build/web
cp target/wasm32-unknown-unknown/release/game.wasm build/web/game.wasm
cp web/game.js build/web/game.js
cp web/index.html build/web/index.html
wavedash.toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./build/web"
Other SDK features
Once initialized, WavedashJS also exposes leaderboards, achievements, stats, and user data. Bridge these the same way -- declare additional extern "C" imports in Rust and provide implementations in web/game.js that call sdk.uploadLeaderboardScore(...), sdk.setAchievement(...), sdk.storeStats(), and sdk.getUser(). See the SDK reference for the full API.