Skip to content

Drawing ​

Scenes draw through draw, an immediate-mode API in logical units. It runs on a batched WebGL2 renderer and falls back to Canvas 2D automatically where WebGL2 isn't available. Your code is the same either way.

ts
render(draw) {
  draw.withCamera(game.camera, () => {
    draw.sprite(heroFrame, hero.x, hero.y, { origin: [0.5, 1], flipX: hero.facingLeft, flash: hero.hurt });
    draw.rect(0, groundY, 320, 8, "#2f3a1f");
    particles.draw(draw);
  });
  draw.text(`score ${score}`, 4, 4, { font: "8px monospace", color: "#cffb2d" });
}

API ​

CallDraws
sprite(frame | image, x, y, options?)An image or sprite-sheet frame. Options: origin, scaleX, scaleY, rotation, flipX, flipY, alpha, tint, flash, smooth
rect(x, y, w, h, color)Filled rectangle
circle(x, y, radius, color)Filled, antialiased circle
line(x1, y1, x2, y2, width, color)Line
text(string, x, y, options?)Cached, crisp text. Options: font, color, align, baseline, alpha
push() / pop(), translate, scale, rotateTransform stack
withCamera(camera, fn)Run fn in the camera's view
clip(x, y, w, h, fn)Draw only inside a rectangle (UI panels, lists, minimaps); nests
alpha, blend("normal" | "add")Global alpha and blend mode
raw{ kind: "webgl2", gl } or { kind: "2d", ctx } escape hatch

Colours are hex strings ("#cffb2d", "#cffb2d80"), any CSS colour, or numbers 0xRRGGBBAA.

Why it's fast ​

Every call becomes one instance in a GPU buffer. Up to 8 textures are bound per batch, so sprites, text and particles interleave without breaking batches. The hot path doesn't allocate.

On the renderer benchmark, draw.sprite sustains about 200,000 sprites at 60 fps. That's about 40× Canvas 2D, about 4× PixiJS Sprite, and level with PixiJS's specialised ParticleContainer. One laptop GPU, so treat these as indicative (ADR 0007).

Choosing a backend ​

ts
new Game({ canvas, width, height, renderer: "auto" }); // default: WebGL2, else Canvas 2D
new Game({ canvas, width, height, renderer: "2d" }); // force Canvas 2D

game.draw.kind tells you which one is active. On Canvas 2D, tint applies only its alpha.