Hooks and creators

Hooks

What a scene or an object asks for while it is being built: loading, input, cameras, lights, sound, state and the game loop.

71 functionsThe descriptions and examples come from the engine's own documentation, which is in English.

Game

useGame

The game itself: its size, its background, whether images are kept crisp, how fast time runs, and whether everything is frozen.

useGame() => TGameHandle
Example
export const Level: TSceneFn = () => {
    const game = useGame();
    const keys = useKeyboard();

    useUpdate(() => {
        // A pause menu: everything stops, everything is still drawn.
        if (keys.justPressed('Escape')) {
            game.isPaused() ? game.resume() : game.pause();
        }
        // Slow motion while the key is held.
        game.setTimeScale(keys.isDown('Shift') ? 0.25 : 1);
    });

    return createScene();
};
Full entry in the reference

Scenes

useScene

Returns the controls for the game's scenes: launch, stop, change, pause, resume and isPaused.

useScene() => TSceneHandle
Example
export const Intro: TSceneFn = () => {
    const scene = useScene();
    let elapsed = 0;
    useUpdate((dt) => {
        elapsed += dt;
        if (elapsed > 3) scene.change('Level');
    });
    return createScene();
};
Full entry in the reference

Lifecycle

useSceneUnmount

Runs your code once, the moment the scene disappears: when it is stopped, when it changes to another scene, or when the whole game is destroyed.

useSceneUnmount(cleanup: () => void) => void
Example
export const Level: TSceneFn = () => {
    const onKey = (event: KeyboardEvent) => console.log(event.key);
    window.addEventListener('keydown', onKey);

    // Without this, the listener stays alive after the level ends and fires in the next scene.
    useSceneUnmount(() => window.removeEventListener('keydown', onKey));

    return createScene();
};
Full entry in the reference

useTimer

Runs code later, in game time: once after a while, or again and again.

useTimer() => TTimer
Example
export const Level: TSceneFn = () => {
    const timer = useTimer();
    const banner = createText({ text: 'READY', font, transform: { x: 160, y: 100 } });

    timer.after(1.5, () => { banner.text = 'GO!'; });
    timer.after(2.5, () => { banner.visible = false; });

    // A new enemy every three seconds, for as long as the level runs
    timer.every(3, () => { spawnEnemy(); });

    return createScene();
};
Full entry in the reference

useUpdate

Runs your code once per frame, for as long as the scene is on screen.

useUpdate(callback: (delta: number, time: number) => void) => void
Example
export const Level: TSceneFn = () => {
    const hero = createSprite({ key: 'hero', transform: { x: 40, y: 112 } });

    useUpdate((delta) => {
        // 100 pixels per second, whatever the screen does
        hero.transform.x += 100 * delta;
    });

    const coin = createSprite({ key: 'coin', transform: { x: 200, y: 100 } });
    useUpdate((delta, time) => {
        // bobs up and down once a second
        coin.transform.y = 100 + Math.sin(time * Math.PI * 2) * 4;
    });

    return createScene();
};
Full entry in the reference

Game objects

useSelf

The thing being built right now, so it can refer to itself later: almost always to end its own life once it has done its job.

useSelf() => TBox
Example
const Spark = () => {
    const self = useSelf();
    let left = 0.4;

    useUpdate((delta) => {
        left -= delta;
        if (left <= 0) {
            destroy(self);
        }
    });
};
Full entry in the reference

useSpawn

Prepares a maker for component, so the scene can create as many of them as it likes, whenever it likes: while it is being built, from a frame, from a timer, from a click.

useSpawn(component: (args: TArgs) => unknown, options: TSpawnOptions) => (args: TArgs) => TBox
Example
declare const gun: TSprite;
declare let firing: boolean;

const Bullet = (x: number) => {
    const self = useSelf();
    const sprite = createSprite({ key: 'bullet', transform: { x, y: 200 } });

    useUpdate((delta) => {
        sprite.transform.y -= 300 * delta;
        if (sprite.transform.y < 0) {
            destroy(self);
        }
    });
};

export const Level: TSceneFn = () => {
    const spawnBullet = useSpawn(Bullet);

    useUpdate(() => {
        if (firing) spawnBullet(gun.transform.x);
    });

    return createScene();
};
Full entry in the reference

useTransform

Gives this object a place of its own, and moves everything inside it.

useTransform(options: TTransformOptions) => TTransform3d
Example
const Turret = (x: number) => {
    const place = useTransform({ x, y: 200 });

    // Both are placed relative to the turret, so turning it turns them together.
    createSprite({ key: 'base', transform: { x: 0, y: 0 } });
    createSprite({ key: 'barrel', transform: { x: 0, y: -12 } });

    useUpdate((delta) => {
        place.rotation += delta;
    });
};
Full entry in the reference

Scripts

useApi

Reaches what another behaviour on the same object published under key.

useApi(key: string, self?: TBox) => () => T | null
Example
registerScript('toggle', () => {
    const spin = useApi<{ stop(): void; start(): void; isRunning(): boolean }>('spin');
    const keys = useKeyboard();

    useUpdate(() => {
        if (!keys.justPressed('Space')) return;
        const api = spin();
        if (api === null) return;
        if (api.isRunning()) api.stop(); else api.start();
    });
}, { requires: ['spin'] });
Full entry in the reference

useScript

Attaches a behaviour by name to the object being built, and runs it.

useScript(ref: string, id?: string, props?: TScriptProps) => void
Example
const Guard = () => {
    const texture = useLoadTexture({ src: '/assets/guard.png' });
    createSprite({ texture, transform: { x: 40, y: 112 } });
    useScript('patrol', undefined, { speed: 80 });
};
Full entry in the reference

Input

useActions

The game's named actions.

useActions(options: TUseActionsOptions) => TActionsHandle
Example
declare const hero: TSprite;
declare const jump: () => void;
declare let charge: number;

export const Player: TSceneFn = () => {
    const input = useActions();

    useUpdate((delta) => {
        // Four actions, one direction: the keys, the d-pad and the stick all arrive here, and the
        // dead zone is round, so a gentle diagonal stays a diagonal.
        const { x, y } = input.vector('move_left', 'move_right', 'move_up', 'move_down');
        hero.transform.x += x * 120 * delta;
        hero.transform.y += y * 120 * delta;

        if (input.justPressed('jump')) jump();
        // A trigger bound to 'fire' reads how far it is pulled; a key bound to it reads 1.
        charge = input.value('fire');
    });

    return createScene();
};
Full entry in the reference

useGamepad

A gamepad, to ask in every frame what the player is holding, has just pressed, or how far a stick is pushed.

useGamepad(target: TGamepadTarget, options: TUseGamepadOptions) => TGamepad
Example
declare const fire: () => void;

export const Level: TSceneFn = () => {
    const pad = useGamepad();
    const keys = useKeyboard();
    const ship = createSprite({ key: 'ship' });

    useUpdate((delta) => {
        const { x, y } = pad.leftStick();
        ship.transform.x += x * 150 * delta;
        ship.transform.y += y * 150 * delta;
        if (pad.justPressed('a') || keys.justPressed('Space')) fire();
    });

    return createScene();
};
Full entry in the reference

useInputMap

Remapping: what a game's controls screen is built on.

useInputMap() => TInputMapHandle
Example
declare const jumpRow: TText;

export const Controls: TSceneFn = () => {
    const map = useInputMap();

    // "Press a key or a button for JUMP..."
    listen(jumpRow, { onClick: () => {
        map.capture((binding) => {
            if (binding === null) return;              // they pressed Escape
            if (map.conflicts(binding, 'jump').length > 0) return;
            map.bind('jump', binding, 0);
        });
    } });

    return createScene();
};
Full entry in the reference

useKeyboard

The keyboard, to ask in every frame what the player is holding or has just pressed.

useKeyboard() => TKeyboard
Example
declare const Bullet: (x: number) => void;

export const Level: TSceneFn = () => {
    const keys = useKeyboard();
    const ship = createSprite({ key: 'ship', transform: { x: 160, y: 200 } });
    const fire = useSpawn(Bullet);

    useUpdate((delta) => {
        if (keys.isDown('ArrowLeft')) ship.transform.x -= 150 * delta;
        if (keys.isDown('ArrowRight')) ship.transform.x += 150 * delta;
        if (keys.justPressed('Space')) fire(ship.transform.x);
    });

    return createScene();
};
Full entry in the reference

usePointer

Listens to the mouse and to touch: presses, releases, movement, and what is under the pointer.

usePointer() => TPointerHandle
Example
export const Board: TSceneFn = () => {
    const pointer = usePointer();
    const red = getColor('#ff5566');

    pointer.onDown((info) => {
        if (info.target !== null) {
            info.target.tint = red;
        }
    });

    // The wheel zooms the camera: towards you is out, away is in.
    const camera = useCamera2d();
    pointer.onWheel(({ deltaY }) => {
        camera.zoom = Math.min(4, Math.max(0.5, camera.zoom * Math.exp(-deltaY * 0.001)));
    });

    return createScene();
};
Full entry in the reference

useVector

Four actions read as one direction: the way to move a character from the input map.

useVector(negativeX: string, positiveX: string, negativeY: string, positiveY: string, options: TUseActionsOptions & { deadzone }) => () => { x, y }
Example
declare const hero: TSprite;
const SPEED = 120;

const move = useVector('move_left', 'move_right', 'move_up', 'move_down');
useUpdate((delta) => {
    const { x, y } = move();
    hero.transform.x += x * SPEED * delta;
    hero.transform.y += y * SPEED * delta;
});
Full entry in the reference

Store

useStore

Reacts from a scene when one value of a store changes, and stops by itself when that part of the scene goes away.

useStore(store: TGameStore<S, A>, selector: TStoreSelector<S, T>, handler: TStoreListener<T>, equals?: (a: T, b: T) => boolean) => void
Example
declare const petStore: TGameStore<{ hunger: number }>;
const GREEN = getColor('#40c040');
const RED = getColor('#e04040');

export const Pet: TSceneFn = () => {
    const pet = createSprite({ tint: GREEN, width: 64, height: 64 });
    useStore(petStore, (s) => s.hunger > 30, (content) => {
        pet.tint = content ? GREEN : RED;
    });
    return createScene();
};
Full entry in the reference

useStoreLink

Says that this object uses one of the game's stores.

useStoreLink(key: string) => void
Example
const Pet = () => {
    useStoreLink('pet');
    // ...and now a behaviour on this object can reach it with storeOf(self).
};
Full entry in the reference

State

useData

State that lives with a piece of the scene, as [data, setData].

useData(initial: T) => [TDataRecord<T>, TDataSetter<T>]
Example
declare const counter: TText;

export const Level: TSceneFn = () => {
    const [lives, setLives] = useData(3);

    useWatch(() => {
        counter.text = `LIVES ${lives.value}`;
    }, [lives]);

    usePointer().onDown(() => setLives((n) => n - 1));

    return createScene();
};
Full entry in the reference

useWatch

Runs your code on the first frame, and again whenever one of the things you listed changes.

useWatch(fn: () => void, deps: typeOperator) => void
Example
declare const counter: TText;
declare const hero: TSprite;

export const Level: TSceneFn = () => {
    const texture = useLoadTexture({ src: '/assets/hero.png' });
    const [lives, setLives] = useData(3);

    useWatch(() => {
        counter.text = `LIVES ${lives.value}`;
        hero.visible = texture.status === 'ready';
    }, [lives, texture]);

    return createScene();
};
Full entry in the reference

Signals

useEvent

Declares an event this object can tell whoever holds it, and gives back the function that sends it.

useEvent(name: string) => (payload: T) => boolean
Example
registerScript('button', (self, props) => {
    const pressed = useEvent<{ label: string }>('pressed');
    listen(self, { onClick: () => pressed({ label: String(props.label) }) });
});
Full entry in the reference

useSignal

Listens to a signal from a scene, and stops listening by itself when that part of the scene goes away.

useSignal(signal: TGameSignal<T>, handler: TSignalHandler<T>) => void
Example
declare const coinCollected: TGameSignal<number>;

export const Hud: TSceneFn = () => {
    let score = 0;
    useSignal(coinCollected, (points) => { score += points; });
    return createScene();
};
Full entry in the reference

Particles

useParticleCollider2d

Makes this object solid to particles in a flat scene: sparks bounce off it and rain ends on it.

useParticleCollider2d(options: { shape, enabled }) => TParticleCollider2d
Example
const Ledge = () => {
    useTransform({ x: 200, y: 300 });
    useParticleCollider2d({ shape: { kind: 'rect', width: 120, height: 16 } });
};
Full entry in the reference

useParticleCollider3d

Makes this object solid to particles in three dimensions.

useParticleCollider3d(options: { shape, enabled }) => TParticleCollider3d
Example
const Step = (y: number, z: number) => {
    useTransform({ y, z });
    createMesh({ geometry: useCubeGeometry() });
    useParticleCollider3d({ shape: { kind: 'box', size: [1, 1, 1] } });
};
Full entry in the reference

Camera

useCamera2d

Gives the scene a camera, so its world can be bigger than the screen and scroll, turn and zoom.

useCamera2d(options?: TCamera2dOptions) => TCamera2d
Example
export const Level: TSceneFn = () => {
    const camera = useCamera2d();
    const hero = createSprite({ key: 'hero', transform: { x: 900, y: 600 } });

    useUpdate(() => {
        // The screen is 480x320: half of it keeps the hero in the middle
        camera.transform.x = hero.transform.x - 240;
        camera.transform.y = hero.transform.y - 160;
    });

    return createScene();
};
Full entry in the reference

useCamera3d

Gives the scene a camera to look at its models through, and returns it.

useCamera3d(options: TCamera3dOptions) => TCamera3d
Example
const Level = () => {
    const camera = useCamera3d({ projection: 'perspective', z: 6 });

    useUpdate((delta) => {
        camera.transform.rotationY += delta * 0.5;
    });

    return createScene();
};
Full entry in the reference

useFog

Puts the scene in fog: its models fade into color between near and far from the camera.

useFog(options: TFogOptions) => TFog
Example
export const Level: TSceneFn = () => {
    useCamera3d({ projection: 'perspective', z: 8 });
    const fog = useFog({ color: getColor('#1a1426'), near: 6, far: 40 });

    useUpdate((delta, time) => {
        // Breathing: the fog comes in and goes out
        fog.far = 40 + Math.sin(time) * 10;
    });

    return createScene();
};
Full entry in the reference

useScreenSpace

Keeps what is created here fixed on the screen, even while the scene's camera moves.

useScreenSpace(on: boolean) => void
Example
const Hud = () => {
    useScreenSpace();
    createSprite({ tint: getColor('#4ade80'), width: 120, height: 8, transform: { x: 70, y: 16 } });
};

export const Level: TSceneFn = () => {
    useCamera2d();
    useSpawn(Hud)();
    return createScene();
};
Full entry in the reference

Lighting

useAmbientLight

The level everything is lit to before any lamp reaches it.

useAmbientLight(options: { color, intensity }) => TAmbientLight
Example
const Level = () => {
    useCamera3d({ projection: 'perspective', z: 5 });
    useAmbientLight({ intensity: 1.2 });
    createMesh({ geometry: useUvSphereGeometry() });

    return createScene();
};
Full entry in the reference

useBlobShadow

Puts a soft dark disc on the ground under something and keeps it there.

useBlobShadow(options: TBlobShadowOptions) => TMesh
Example
const Level = () => {
    useCamera3d({ projection: 'perspective', y: 3, z: 6, rotationX: -0.5 });
    createMesh({ geometry: usePlaneGeometry({ width: 12, depth: 12 }) });

    const hero = createMesh({ geometry: useCubeGeometry(), transform: { y: 0.5 } });
    useBlobShadow({ target: hero, radius: 0.75, followHeight: true });

    return createScene();
};
Full entry in the reference

usePointLight

A lamp: it has a place, shines every way, and fades out with distance.

usePointLight(options: TLightOptionsBase & { range }) => TPointLight
Example
const Level = () => {
    useCamera3d({ projection: 'perspective', z: 5 });
    usePointLight({ intensity: 1.2 });
    createMesh({ geometry: useUvSphereGeometry() });

    return createScene();
};
Full entry in the reference

useSpotLight

A torch: a lamp that only shines inside a cone.

useSpotLight(options: TLightOptionsBase & { range, angle, penumbra }) => TSpotLight
Example
const Level = () => {
    useCamera3d({ projection: 'perspective', z: 5 });
    useSpotLight({ intensity: 1.2 });
    createMesh({ geometry: useUvSphereGeometry() });

    return createScene();
};
Full entry in the reference

Geometry

Animation

useSkeletalAnimation

Makes a loaded model move: plays the movements it came with, and eases between them.

useSkeletalAnimation(model: TGltfModel, options: TSkeletalAnimationOptions) => TSkeletalAnimation
Example
export const Level: TSceneFn = () => {
    useCamera3d({ projection: 'perspective', z: 200 });
    useLight({ intensity: 1 });

    const fox = useLoadGltf({ src: '/models/fox.glb' });
    createModel({ model: fox });
    const moves = useSkeletalAnimation(fox, { play: 'Walk', fade: 0.25 });

    const keys = useKeyboard();
    useUpdate(() => {
        if (keys.justPressed('Space')) moves.play('Run');
    });

    return createScene();
};
Full entry in the reference

useSpriteAnimation

Plays a sprite's pictures in order, so it walks, attacks or spins.

useSpriteAnimation(sprite: TSprite, options: TSpriteAnimationOptions) => TSpriteAnimation
Example
declare const walk: TSpriteAtlas;
declare let hurt: boolean;

const enemy = createSprite({ atlas: walk, frame: 0, transform: { x: 80, y: 120 } });

const anim = useSpriteAnimation(enemy, {
    clips: {
        walk: { frames: [0, 1, 2, 3, 4, 5], fps: 12 },
        hit: { frames: [6, 7], fps: 20, loop: false },
    },
    play: 'walk',
});

useUpdate(() => {
    if (hurt) anim.play('hit');
});
Full entry in the reference

useTween

Moves a number from one value to another over time, so something can slide in, grow, fade or bounce without you writing the arithmetic for it every frame.

useTween() => TTweenStarter
Example
export const Level: TSceneFn = () => {
    const hero = createSprite({ key: 'hero', transform: { x: 40, y: 112 } });
    const tween = useTween();

    // There and back for ever, landing with a bounce on each end
    tween({
        from: 40,
        to: 420,
        duration: 1.5,
        ease: easeOutBounce,
        yoyo: true,
        repeat: -1,
        onUpdate: (x) => { hero.transform.x = x; },
    });

    return createScene();
};
Full entry in the reference

Post-processing

usePostProcess

Adds a full-screen effect: a shader that reads the finished frame and gives back what to show.

usePostProcess(options: TPostProcessOptions<U>) => TPostEffect<U>
Example
const Level = () => {
    const nes = useLoadPalette({ src: '/palettes/nes.palette' });

    usePostProcess({ ...paletteMatch(), palette: nes });

    return createScene();
};
Full entry in the reference

Color & palettes

Audio

useAudio

The game's volumes: the general one and one per channel, plus a way to silence everything.

useAudio() => TAudioHandle
Example
declare const settings: TGameStore<{ music: number }>;
declare const quieter: TText;

export const Options: TSceneFn = () => {
    const audio = useAudio();
    audio.setVolume(settings.state.music, 'music');

    listen(quieter, { onClick: () => audio.setVolume(audio.getVolume('music') - 0.1, 'music') });
    return createScene();
};
Full entry in the reference

useAudioListener

Puts the game's ears on this object: every sound placed in the world is heard from where it is, and in a 3D scene, facing the way it faces.

useAudioListener(options: { enabled }) => TAudioListener
Example
const Player = () => {
    useTransform({ x: 0, y: 0.5, z: 0 });
    createMesh({ geometry: useCubeGeometry() });
    useAudioListener();
};
Full entry in the reference

useMusic

Plays a piece of music made of layers, and hands back the controls for it.

useMusic(options: TMusicOptions) => TMusicHandle
Example
declare const player: TSprite;

const Level = () => {
    const music = useMusic({
        layers: {
            land: { src: '/audio/theme_land.ogg' },
            water: { src: '/audio/theme_water.ogg', volume: 0 },
        },
        autoplay: true,
    });

    useUpdate(() => {
        const under = player.transform.y < 0;
        music.setLayer('land', under ? 0 : 1, 0.5);
        music.setLayer('water', under ? 1 : 0, 0.5);
    });
    return createScene();
};
Full entry in the reference

useSound

Plays a sound, and hands back the controls for it.

useSound(source: TSoundSource, options: TSoundOptions) => TSoundHandle
Example
export const Level: TSceneFn = () => {
    const music = useSound({ src: '/audio/theme.mp3' }, { channel: 'music', loop: true, autoplay: true });
    const jump = useSound({ src: '/audio/jump.mp3' }, { volume: 0.6 });
    const keys = useKeyboard();

    useUpdate(() => {
        if (keys.justPressed('Space')) jump.play();
    });

    useSignal(scenePaused, () => music.setVolume(0.2));
    return createScene();
};
Full entry in the reference

Assets & loading

useLoadAtlas

Loads a sheet written as a file: the image, how it is cut into frames, and the named runs of frames over it.

useLoadAtlas(options: TUseLoadAtlasOptions) => TLoadedAtlas
Example
export const Level: TSceneFn = () => {
    const coin = useLoadAtlas({ src: '/assets/atlases/coin.atlas' });

    const sprite = createSprite({ atlas: coin, transform: { x: 160, y: 120 } });
    // The runs come from the file, so the clip is not written twice.
    useSpriteAnimation(sprite, { clips: coin.sequences, play: 'spin' });

    return createScene();
};
Full entry in the reference

useLoadAudio

Loads a sound, and hands it back at once, still loading, for useSound to play.

useLoadAudio(options: TUseLoadAudioOptions) => TAudioClip
Example
declare const chest: TSprite;

export const Level: TSceneFn = () => {
    const coin = useLoadAudio({ src: '/audio/coin.mp3', key: 'coin' });
    const pickup = useSound(coin);
    listen(chest, { onClick: () => pickup.play() });
    return createScene();
};
Full entry in the reference

useLoader

Keeps count of what a scene is loading, for a loading bar or to wait before changing scene.

useLoader(assets?: typeOperator) => TLoader
Example
export const Loading: TSceneFn = () => {
    const scene = useScene();
    const loader = useLoader([
        useLoadTexture({ src: '/assets/hero.png', key: 'hero' }),
        useLoadTexture({ src: '/assets/tiles.png', key: 'tiles' }),
    ]);
    const bar = createSprite({ width: 0, height: 8, transform: { x: 60, y: 112 } });
    useUpdate(() => {
        bar.width = loader.progress * 200;
        if (loader.done) scene.change('Level');
    });
    return createScene();
};
Full entry in the reference

useLoadFont

Loads a bitmap font: an image with the characters drawn in it, and a file saying where each one is.

useLoadFont(options: TUseLoadFontOptions) => TFont
Example
export const Title: TSceneFn = () => {
    const font = useLoadFont({
        json: '/fonts/arcade/arcade.json',
        atlas: '/fonts/arcade/arcade.png',
    });

    createText({ text: 'PRESS START', font, transform: { x: 16, y: 16 } });

    return createScene();
};
Full entry in the reference

useLoadGltf

Loads a model made somewhere else: something sculpted in Blender, bought in a pack, exported from anywhere that writes glTF.

useLoadGltf(options: TUseLoadGltfOptions) => TGltfModel
Example
export const Level: TSceneFn = () => {
    useCamera3d({ projection: 'perspective', z: 6 });
    useLight({ intensity: 1 });

    const tower = useLoadGltf({ src: '/models/tower.glb' });
    const placed = createModel({ model: tower });

    useUpdate((delta) => {
        placed.transform.rotationY += delta * 0.5;
    });

    return createScene();
};
Full entry in the reference

useLoadPack

Loads a pack: boxes and scenes somebody made in another project, with everything they need.

useLoadPack(options: TUseLoadPackOptions) => TLoadedPack
Example
const Plaza: TSceneFn = () => {
    const signs = useLoadPack({ src: '/packs/signpost' });
    createPack({ pack: signs, box: 'Signpost', transform: { x: 100, y: 120 } });
    return createScene();
};
Full entry in the reference

useLoadShader

Loads a shader written in a file, so an effect can live beside the game instead of inside it.

useLoadShader(options: TUseLoadShaderOptions) => TShader
Example
export const Level: TSceneFn = () => {
    const crt = useLoadShader({ src: '/shaders/crt.wgsl' });
    const texture = useLoadTexture({ src: '/assets/hero.png' });

    createSprite({ texture, material: createMaterial({ effect: crt, uniforms: { lines: 80 } }) });

    return createScene();
};
Full entry in the reference

useLoadTexture

Loads an image to draw with, and hands it back at once, still loading: a sprite made with it appears by itself when the file arrives, so nothing has to wait for it.

useLoadTexture(options: TUseLoadTextureOptions) => TTexture
Example
export const Level: TSceneFn = () => {
    const hero = useLoadTexture({ src: '/assets/hero.png', key: 'hero' });
    createSprite({ texture: hero });
    return createScene();
};
Full entry in the reference

Physics

usePhysicsBody2d

Gives this object a flat shape to collide with.

usePhysicsBody2d(options: TPhysicsBody2dOptions) => TPhysicsBody2d
Example
const BROWN = getColor('#8b5a2b');

const Crate = (x: number, y: number) => {
    createSprite({ tint: BROWN, width: 24, height: 24, transform: { x, y } });
    usePhysicsBody2d({ body: 'dynamic', collider: { shape: 'rect', width: 24, height: 24 }, restitution: 0.2 });
};
Full entry in the reference

usePhysicsWorld2d

Opens the flat simulation for this scene, and says how hard things fall.

usePhysicsWorld2d(options: { id, gravity }) => TPhysicsWorld2d
Example
export const Level: TSceneFn = () => {
    usePhysicsWorld2d({ gravity: { x: 0, y: 900 } });
    // ...then objects with usePhysicsBody2d, which fall in it.
    return createScene();
};
Full entry in the reference

Math

useRandom

The random numbers of this game.

useRandom() => TRandomHandle
Example
export const Level: TSceneFn = () => {
    const random = useRandom();

    for (let i = 0; i < 20; i++) {
        createSprite({ key: 'tree', transform: { x: random.rand(0, 480), y: random.rand(0, 320) } });
    }

    return createScene();
};
Full entry in the reference

Debug

useHelperAxis

Draws the three axes as coloured lines from where it is placed: X red, Y green, Z blue, the colours every 3D tool uses.

useHelperAxis(options: TUseHelperAxisOptions) => TLines
Example
const Level = () => {
    useCamera3d({ projection: 'perspective', fov: 60, y: 1, z: 4, rotationX: -0.2 });
    useHelperAxis({ size: 2, negative: true });
    return createScene();
};
Full entry in the reference

useHelperGrid

Draws a floor grid on the ground plane, the one every 3D editor shows, with its middle lines in the colours of the X and Z axes.

useHelperGrid(options: TUseHelperGridOptions) => TLines
Example
const Level = () => {
    useCamera3d({ projection: 'perspective', fov: 60, y: 4, z: 8, rotationX: -0.45 });
    useHelperGrid({ half: 5 });
    return createScene();
};
Full entry in the reference

useHelperLines

Draws any lines you like, and hands back the function that replaces them at any time.

useHelperLines(options: TUseHelperLinesOptions) => THelperLines
Example
declare const target: { x: number; y: number; z: number };

const Level = () => {
    useCamera3d({ projection: 'perspective', fov: 60, z: 6 });
    const [, setPath] = useHelperLines();

    useUpdate(() => {
        // One yellow line from the origin to wherever the enemy is heading.
        setPath(new Float32Array([0, 0, 0, 1, 1, 0, 1, target.x, target.y, target.z, 1, 1, 0, 1]));
    });

    return createScene();
};
Full entry in the reference