Draw and animate sprites
Try the minimal sprite example. It displays four source frames and an animated sprite with pause/resume controls, independently of physics or state machines.
A sprite sheet owns decoded images and immutable frame handles. Sprite draws a
frame; an ordinary animation program can change a frame signal.
Draw one frame
Section titled “Draw one frame”Start with a regular grid. This complete mount function draws its first cell and returns cleanup for the caller to run when leaving the page.
import { pibbl } from "@pibbl/core";import { Sprite, loadSpriteSheet } from "@pibbl/core/sprites";
export async function mountSprite(canvas: HTMLCanvasElement) { const sheet = await loadSpriteSheet("/coin.png", { grid: { frameWidth: 32, frameHeight: 32 }, }); try { const app = pibbl( canvas, <Sprite frame={sheet.frames[0]} sampling="nearest" />, ); return () => { app.dispose(); // Unmount consumers before releasing their images. sheet.dispose(); }; } catch (error) { sheet.dispose(); throw error; }}Animate a frame signal
Section titled “Animate a frame signal”For an Aseprite export with a standing frame and a walk tag:
import { drive, repeat, usePlayback, useSignal } from "@pibbl/core";import { Sprite, loadSpriteSheet } from "@pibbl/core/sprites";import { aseprite } from "@pibbl/core/sprites/formats/aseprite";
const sheet = await loadSpriteSheet("/hero.json", { format: aseprite() });
function Walker() { const frame = useSignal(sheet.frames.standing); usePlayback( repeat(drive(frame, sheet.animations.walk), { iterations: Infinity, }), { autoplay: true }, ); return <Sprite frame={frame} sampling="nearest" />;}Load assets before mounting this component, or conditionally mount it after a loading task succeeds. The owner must dispose the sheet after its consumers unmount. Sharing a sheet does not transfer its ownership to each sprite.
Grids and custom clips
Section titled “Grids and custom clips”import { loadSpriteSheet, defineSpriteAnimation } from "@pibbl/core/sprites";
const sheet = await loadSpriteSheet("/coin.png", { grid: { frameWidth: 32, frameHeight: 32, margin: 0, spacing: 0 },});const spin = defineSpriteAnimation({ frames: Object.values(sheet.frames), fps: 12,});Grid frames have numeric-string names in row order. Use explicit timed entries
{ frames: [{ frame, duration }, ...] } for unequal frame durations, measured in
milliseconds. Clips are finite; looping belongs to repeat, seeking and pausing
to playback. Interior frame boundaries select the next frame; the final sample
selects the last frame.
Reverse the same clip through the animation program, without copying its frames:
import { drive, repeat } from "@pibbl/core";
const backward = repeat(drive(frame, spin), { direction: "reverse", iterations: Infinity,});Here frame is the writable frame signal passed to Sprite, and spin is the
clip above. Pass backward to usePlayback, just like the walking program.
Packed formats and geometry
Section titled “Packed formats and geometry”Import aseprite() or texturePacker() from their own format modules. The loader
calls the supplied parser; there is no format registry or string dispatch that
pulls every parser into the bundle. Aseprite tags supply named clips. Unsupported
TexturePacker scale/multipack metadata fails explicitly.
import { loadSpriteSheet } from "@pibbl/core/sprites";import { texturePacker } from "@pibbl/core/sprites/formats/texture-packer";
const sheet = await loadSpriteSheet("/terrain.json", { format: texturePacker(),});// Use sheet.frames with the exact frame names from the exported JSON.Frames preserve source dimensions, trim offsets, and packing rotation. Sprite
size and normalized anchor use original logical dimensions rather than the packed
rectangle, avoiding jitter from trimming. flipX/flipY mirror the frame, while
sampling="nearest" preserves hard pixel edges; linear sampling is the default.
Use explicit physical colliders: atlas transparency is not collision geometry.
Artwork review
Section titled “Artwork review”Measure generated atlas rectangles rather than assuming cells are aligned. Check unique poses, baseline alignment, transparency, neighboring pixels, and the loop at its intended display size and speed. More frames help only when their poses form a coherent cycle. The Brick Climb showcase combines sprites, physics, and state machines, and includes a separate sprite inspector for that review. Its showcase page explains how to run the game locally.
See animation for playback composition and machine animation for event-driven coordination.
Open the interactive workbench
Implementation guidance for agents
Section titled “Implementation guidance for agents”Read the Authoring, signals, and lifecycle companion for ownership, adaptation, failure modes, and verification. Agent start provides the version-selection workflow.
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.