Hello World
Let's take a look at an example of a basic program: Drawing a rectangle.
import * as w4 from "./wasm4";
export function update (): void { w4.rect(10, 10, 32, 32);}
#include "wasm4.h"
void update () { rect(10, 10, 32, 32);}
import w4;
fn void update() @wasm { w4::rect(10, 10, 32, 32);}
import w4 = wasm4;
extern(C) void update() { w4.rect(10, 10, 32, 32);}
package main
import "cart/w4"
//go:export updatefunc update () { w4.Rect(10, 10, 32, 32)}
require "wasm4"
local function update () rect(10, 10, 32, 32)end
## setup_wasm4_callbacks(update)
import cart/wasm4
proc update {.exportWasm.} = rect(10, 10, 32, 32)
package main
import "w4"
@exportupdate :: proc "c" () { w4.rect(10, 10, 32, 32)}
import "wasm4.pn";
pub extern fn update(){ rect(10, 10, 32, 32);}
import proc rect int int int int in end
export main "start"proc main in end
export update "update"proc update in // Draw a rectangle at (10, 10) with size (32, 32). 32 32 10 10 rectend
proc start() {}
proc update() { rect(10, 10, 32, 32);}
mod wasm4;use wasm4::*;
#[no_mangle]fn update () { rect(10, 10, 32, 32);}
(import "env" "rect" (func $rect (param i32 i32 i32 i32)))
(func (export "update") ;; Draw a rectangle at (10, 10) with size (32, 32). (call $rect (i32.const 10) (i32.const 10) (i32.const 32) (i32.const 32)))
const w4 = @import("wasm4.zig");
export fn update() void { w4.rect(10, 10, 32, 32);}
note
Sometimes we may need to initialize a few things before starting our game. On these occasions, a start()
function can be used, which will be called only once, which is when the game is started.
The first line imports the WASM-4 API definitions. This is a stub source file included with all projects that describes which functions are available.
One of those functions is rect()
, which we use to draw a 32x32 rectangle at position (10, 10).
We place this in a callback function called update()
which is marked for export to WebAssembly
(exact syntax varies by language). The WASM-4 runtime calls the update()
callback every frame, at
60 frames per second.
#
Accessing MemoryMemory in WebAssembly is a contiguous, linear block that can be randomly accessed. WASM-4 reserves a region of that memory to map its state registers.
One of those registers is DRAW_COLORS
at address $14. Its value affects the color of all drawing
functions. Let's draw a different color rectangle by setting DRAW_COLORS
to 2 (the second color in
the palette).
store<u16>(w4.DRAW_COLORS, 2);
w4.rect(10, 10, 32, 32);
*DRAW_COLORS = 2;
rect(10, 10, 32, 32);
*w4::DRAW_COLORS = 2;
w4::rect(10, 10, 32, 32);
*w4.drawColors = 2;
w4.rect(10, 10, 32, 32)
*w4.DRAW_COLORS = 2
w4.Rect(10, 10, 32, 32)
$DRAW_COLORS = 2
rect(10, 10, 32, 32)
DRAW_COLORS[] = 2
rect(10, 10, 32, 32)
w4.DRAW_COLORS^ = 2
w4.rect(10, 10, 32, 32)
DRAW_COLORS = 2;
rect(10, 10, 32, 32);
// Set DRAW_COLORS to 2.2 $DRAW_COLORS !16
// Draw a rectangle at (10, 10) with size (32, 32).32 32 10 10 rect
DRAW_COLORS~ = 2;
rect(10, 10, 32, 32);
unsafe { *DRAW_COLORS = 2 }
rect(10, 10, 32, 32);
;; Set DRAW_COLORS to 2.(i32.store16 (global.get $DRAW_COLORS) (i32.const 2))
;; Draw a rectangle at (10, 10) with size (32, 32).(call $rect (i32.const 10) (i32.const 10) (i32.const 32) (i32.const 32))
w4.DRAW_COLORS.* = 2;
w4.rect(10, 10, 32, 32);
#
DebuggingUse trace()
to output a message to the console, which can be very useful for quick debugging.
w4.trace("Hello world!");
trace("Hello world!");
w4::trace("Hello world!");
w4.trace("Hello world!");
w4.Trace("Hello world!")
trace("Hello World!")
trace("Hello world!")
w4.trace("Hello world!")
trace("Hello world!");
import proc trace ptr in end
"Hello world!"c trace
trace("Hello world!");
trace("Hello world!");
(import "env" "trace" (func $trace (param i32)))
;; Put the string at address 0x2000 in memory.(data (i32.const 0x2000) "Hello world!\00")
(call $trace (i32.const 0x2000))
w4.trace("Hello world!");
tip
Press F8
to toggle the WASM-4 developer tools, which displays system state, memory usage, and more.