Skip to content

picogame — quick reference

A one-page cheat sheet of everything the engine exposes: the native picogame C module and the pure-Python picogame_* helper libraries in lib/. Signatures show parameter names and defaults; * marks keyword-only arguments. Colours are wire-order RGB565 ints (build them with rgb565). For longer explanations see PICOGAME.md.


Native module: picogame (import picogame as pg)

Section titled “Native module: picogame (import picogame as pg)”
  • RGB565, PAL8 — bitmap pixel formats.
  • rgb565(r, g, b) -> int — wire-order colour from 8-bit channels.
  • collide(x1, y1, x2, y2, ax1, ay1, ax2, ay2) -> bool — AABB overlap (8 args = box vs box) or point-in-box (6 args: collide(x1, y1, x2, y2, px, py)). Inclusive AABB — boxes collide when they touch (pass sprite boxes as (x, y, x+w, y+h); fires on contact). Note: collide is inclusive, unlike render’s half-open pixel ranges — different domains (hitboxes vs pixels).

Bitmap(data, width, height, *, format=RGB565, palette=None, frames=1, stride=0, transparent=None)

Section titled “Bitmap(data, width, height, *, format=RGB565, palette=None, frames=1, stride=0, transparent=None)”

An image atlas of equal-size frames (any size). data is a buffer; palette (array of wire colours) is required for PAL8. transparent = the index/colour skipped when blitting.

  • Read-only props: width, height, frames, format, stride, palette (the PAL8 palette buffer or None), transparent (the transparent value or None).

Sprite(bitmap, x=0, y=0, *, frame=0, visible=True, flip_x=False, flip_y=False)

Section titled “Sprite(bitmap, x=0, y=0, *, frame=0, visible=True, flip_x=False, flip_y=False)”

A positioned, animatable instance of a Bitmap.

  • Position/anim props: x, y (int px) · fx, fy (float sub-pixel) · frame · visible · flip_x, flip_y · bitmap (swap) · data (your payload).
  • Transform props (nearest-neighbour, about the anchor):
    • scale — float draw scale; 1.0 = native (fast path), 2.0 = double size, fractional allowed (e.g. a pulse).
    • angle — rotation in degrees; 0 = none (fast path). Combines with scale.
    • transpose — bool; swap X/Y axes → a cheap 90° rotation (with flip_x/flip_y = all 8 orientations), crisp, no shimmer. Fast path only (scale 1, angle 0); footprint swaps w/h.
    • anchor = (fx, fy) — pivot as fractions of the bitmap (0..1): (0.5, 0.5) = centre, (0.5, 1.0) = bottom-centre. x/y and rotation are about this point.
  • Blit-effect props (one at a time; setting one clears the others; cheap, no extra bitmaps):
    • shadow — bool; opaque pixels darken the destination (drop-shadow / dim overlay).
    • flash — wire-RGB565 colour (or 0/None = off); opaque pixels drawn as that flat colour (hit-flash). Pulse 1–3 frames.
    • tint — wire-RGB565 colour (or 0 = off); opaque pixels multiplied by it — colours the sprite while keeping its shading (damage-red, freeze-blue, glow).
    • dither0 (opaque) .. 16 (invisible); Bayer-stipple translucency, no alpha (ghosts, fog, fade-in/out).
  • move(x, y) — set position. · touch() — mark dirty after an in-place bitmap/palette edit.

Fast DMA backend wrapping a board’s busdisplay (FourWire SPI). Pass to Scene.

Scene(display, buffer_a, buffer_b, *, background=0, top=0, bottom=0, left=0, right=0)

Section titled “Scene(display, buffer_a, buffer_b, *, background=0, top=0, bottom=0, left=0, right=0)”

Retained-mode scene with dirty-rectangle rendering; buffer_a/b are strip buffers.

  • add(item, *, fixed=False) -> item — add a Sprite/Tilemap/Particles/Canvas/StripDraw (insertion order = bottom→top) and return it (so spr = scene.add(Sprite(...)) works). fixed=True (keyword-only) pins it to the screen (ignores the camera) for HUD/dialog.
  • add_all(items) — add several (bottom→top).
  • set_view(ox, oy) — camera offset (screen position of the scene origin); changing it repaints all.
  • view — read-only (ox, oy) camera offset.
  • invalidate() — force a full repaint next refresh.
  • refresh() -> list | None — diff & repaint changed regions; returns the dirty rect [x1,y1,x2,y2] (reused) or None.

A grid of tile indices into a tileset Bitmap (each frame = one tile); a Scene layer.

  • tile(tx, ty, value=None, *, flip_x=False, flip_y=False, transpose=False) -> int — get tile, or set it (with optional keyword-only per-cell orientation: flip_x/flip_y/transpose give all 8 orientations of a tile — pair with a deduplicated tileset, see png2picogame.py --dedup). Out-of-range ignored. The orientation plane is allocated lazily (RAM only if a map uses it).
  • fill(value) — set every tile (clears orientation).
  • move(x, y) — position the map.
  • Read-only props: x, y, cols, rows.

Particles(capacity, size=1, gravity=0.0, fade=False)

Section titled “Particles(capacity, size=1, gravity=0.0, fade=False)”

A pooled particle layer (small moving dots) drawn as one Scene layer.

  • emit(x, y, count, speed=1, life=30, color=0xFFFF) — burst count dots, random velocity ≤ speed px/tick, living life ticks.
  • tick() — advance one step (move, gravity, ageing). Call each frame.
  • clear() — remove all.

Canvas(width, height, transparent=None, buffer=None)

Section titled “Canvas(width, height, transparent=None, buffer=None)”

A RAM RGB565 drawing surface composited as a Scene layer (width*height*2 bytes). transparent makes it a shaped overlay; buffer backs it with external memory (e.g. an arena slice). For animated full-frame surfaces prefer StripDraw (no buffer).

  • clear(color) · pixel(x, y, color) · fill_rect(x, y, w, h, color) · rect(x, y, w, h, color)
  • line(x0, y0, x1, y1, color) · circle(cx, cy, r, color) · fill_circle(cx, cy, r, color) · ring(cx, cy, r, thickness, color)
  • triangle(x0,y0, x1,y1, x2,y2, color) · fill_triangle(...) · ellipse(cx, cy, rx, ry, color) · fill_ellipse(...)
  • fill_round_rect(x, y, w, h, r, color) · frame3d(x, y, w, h, light, dark) (beveled box) · move(x, y)
  • Read-only props: x, y, width, height.

StripDraw(callback, x=0, y=0, width=0, height=0)

Section titled “StripDraw(callback, x=0, y=0, width=0, height=0)”

Immediate-mode layer with no pixel buffer: each refresh it calls callback(view, vx, vy, vw, vh) once per render strip inside its rect. view is a Canvas pointing at the live strip (use Canvas primitives); view-local (0,0) = screen (vx, vy). Repaints every frame → for animated/scanline content (pseudo-3D, gradients). In a scrolling scene add it fixed.

  • Read/write props: x, y, width, height — move or resize the layer (after shrinking, call scene.invalidate()).

Procedural noise (coherent value noise, 0..1)

Section titled “Procedural noise (coherent value noise, 0..1)”
  • value2d(x, y, *, seed=0) -> float · value1d(x, *, seed=0) -> float
  • fbm2d(x, y, *, octaves=4, seed=0, lacunarity=2.0, gain=0.5) -> float · fbm1d(x, *, octaves=4, seed=0, lacunarity=2.0, gain=0.5) -> float — fractal (summed octaves).

Helper libraries (lib/picogame_*.py, pure Python)

Section titled “Helper libraries (lib/picogame_*.py, pure Python)”
  • setup(display=None, strip_h=24, background=0, fast=True) -> (scene, buffer_a, buffer_b) — take over the display, build a Scene + two strip buffers.
  • Clock(fps=30, max_dt=0.1) · .set_fps(fps) · .tick() -> dt (sleep to frame, return seconds) · .tick_async().
  • FixedStep(step_fps=60, max_steps=5) · .steps() — generator yielding a constant dt per fixed step.
  • Masks: UP DOWN LEFT RIGHT A B X Y ALL; profile PICOPAD.
  • Buttons(profile=None, pull=None) · .poll() -> mask · .is_pressed(mask=ALL) · .just_pressed(mask=ALL) · .just_released(mask=ALL) · .repeat(button, delay=15, interval=4) — PICO-8 btnp auto-repeat (menus / grid move).
  • Timer(frames) — input-leniency window (coyote time / jump buffering): .feed(cond) (recharge while true, else decay) · .charge() · .is_active · .consume() (true once, then clears).
  • render_text(pg, font, text, fg, bg=None) -> (bitmap, w, h) — render a string to a PAL8 Bitmap (bg=None → transparent).
  • render_text_pal(pg, font, text, fg, bg=None) -> (bitmap, w, h, palette) — same, plus the palette array; mutate palette[1] to recolour the text in place (no rebuild).
  • Label(pg, font, x, y, fg, bg) · .move(x, y) · .set(text) -> changed · .draw(display, buffer).
  • SceneLabel(scene, pg, font, x, y, fg, bg) · .set(text) — camera-independent text label (a fixed Scene layer).
  • TextBox(pg, font, x, y, w, h, fg, bg, maxlines=6) · .draw(display, buffer, lines).
  • Menu(pg, font, x, y, items, fg, bg, title=None) · .tick(btn) -> index | -1 · .draw(display, buffer).

picogame_shapes — single-colour bitmap generators

Section titled “picogame_shapes — single-colour bitmap generators”
  • rect(w, h, color) · circle(d, color) · ring(d, color, thickness=2)
  • from_mask(mask, color) — Bitmap from a string mask ('#' = set).
  • atlas(frames_data, w, h, color) — pack w×h buffers into a multi-frame Bitmap.
  • color_frames(w, h, colors) — frame i = solid colors[i].
  • tileset_colors(w, h, colors) — tileset: frame 0 empty, frames 1..N coloured.
  • poly_frames(size, points, nframes, color, fill=True) — bake nframes rotations of a polygon.
  • Pool(scene, bitmap, capacity, anchor=None, fixed=False) · .spawn() -> sprite | None · .free(s) · .free_all() · .count() -> int. (.items = all sprites.)
  • hit(a, b, hw=None, hh=None) — AABB overlap of two sprites.
  • hit_point(a, px, py, hw=None, hh=None) — point in a sprite.
  • is_within(a, b, r) — circular distance test (no sqrt).

picogame_math — vector math (in picogame_math)

Section titled “picogame_math — vector math (in picogame_math)”
  • length(dx, dy) · distance(x1, y1, x2, y2) · normalize(dx, dy) · angle_rad(dx, dy) (radians) · from_angle_rad(a, mag=1.0) · clamp(v, lo, hi).

picogame_math — numeric helpers + turn-based trig

Section titled “picogame_math — numeric helpers + turn-based trig”
  • clamp(v, lo, hi) · mid(a, b, c) · lerp(a, b, t) · inv_lerp(a, b, v) · remap(v, a, b, c, d) · sgn(x) · approach(v, target, step) · wrap(v, lo, hi).
  • sin_t(turns) · cos_t(turns) · atan2_t(dy, dx) -> turns — angles as 0..1 turns (standard, not PICO-8’s inverted sin).

picogame_tiles — per-tile metadata flags (PICO-8 fget/fset)

Section titled “picogame_tiles — per-tile metadata flags (PICO-8 fget/fset)”
  • Bits/masks: B_SOLID B_HAZARD B_LADDER … (indices) and SOLID HAZARD LADDER … (masks).
  • TileFlags(flags=None, tile_px=8)flags = {tile_index: bitfield} or a list. .get(tile, bit=None) · .set(tile, bit, value=True) · .at(tilemap, cx, cy, bit) · .at_px(tilemap, px, py, bit) (collision one-liner). Keyed by tile index (shared by all cells using it).

picogame_seq — generator-driven sequences (coroutine pattern)

Section titled “picogame_seq — generator-driven sequences (coroutine pattern)”
  • wait(frames) · over(frames, fn) (fn(t), t 0..1) · move_over(sprite, x, y, frames) — all are generators; compose with yield from.
  • Seq(gen=None) · .start(gen) · .tick() -> done · .done — advance one step per frame (cutscenes, “do X over N frames”).

picogame_anim — frame animation over time

Section titled “picogame_anim — frame animation over time”
  • FrameAnim(sprite, frames, fps=8, loop=True) · .reset() · .tick(dt).
  • AnimatedSprite(sprite, anims) · .play(name) · .tick(dt).
  • Shake(scene, max_offset=6, decay=0.03) · .add(amount) (0.6 hit, 0.15 bump) · .tick(cam_x=0, cam_y=0) — trauma screen shake composed on top of the camera.
  • Fade(scene, w, h, x=0, y=0, color=0, cell=8) · .out()/.into()/.set(level)/.dim(level)/.pulse() · .tick() -> done — dither fade / dim / flash, full-screen or a region. 0-byte StripDraw overlay.
  • Tween(value=0.0, speed=0.2) · .to(target) · .set(v) · .tick() -> value · .is_done — ease a scalar (UI/pop-ups).
  • Camera(scene, w, h, lerp=0.18, world_w=0, world_h=0) · .follow(tx, ty, snap=False) · .offset() -> (ox,oy) · .apply() — smoothed follow + world clamp (compose with Shake via shake.tick(*cam.offset())).
  • Sky(scene, x, y, w, h, top, bottom) — vertical gradient (per-scanline, 0 RAM). · Scanlines(scene, x, y, w, h, step=2, dark=0) — CRT overlay.

picogame_palette — Game-Boy palette tricks on PAL8 art (call sprite.touch() after)

Section titled “picogame_palette — Game-Boy palette tricks on PAL8 art (call sprite.touch() after)”
  • cycle(palette, lo, hi, step=1) — rotate entries (animated water/lava/portals; ~0 extra art).
  • swap(dst_palette, src_palette) — recolour a shared bitmap (GBC-style; cheaper than a 2nd bitmap).
  • fade(palette, base, t, target=0, skip=None) — lerp toward a colour (smooth brightness fade; base = snapshot() of the original).
  • snapshot(palette) / restore(palette, base).
  • Rand(seed=None) (deterministic xorshift; None = time-seeded) · .below(n) · .randint(a, b) · .random() · .chance(p) · .choice(seq) · .shuffle(lst) · .weighted(weights) -> index · .seed(s).
  • Bag(items, rng) · .next() — shuffle-bag (7-bag) anti-streak randomizer.

Noise — native picogame functions (pg.*)

Section titled “Noise — native picogame functions (pg.*)”
  • value2d, value1d, fbm2d, fbm1d are functions on the native picogame module itself (call as pg.value2d, pg.value1d, pg.fbm2d, pg.fbm1d); there is no separate picogame_noise module.
  • Save(key, schema, *, offset=0) · .defaults() · .load() -> dict · .save(values) · .reset(). Survives reboot/filesystem wipe.
  • Audio(pin=None, voices=4, sample_rate=22050, channels=1, bits=16, signed=True) · .load(path) · .play(sample, *, voice=None, loop=False, volume=1.0) · .sfx(sample, volume=1.0) · .music(sample, loop=True, volume=1.0) · .stop(voice=None) · .stop_music() · .is_playing.
  • tone(frequency=440, ms=120, sample_rate=22050, volume=0.6) — square-wave beep sample.

picogame_arena — anti-fragmentation buffer

Section titled “picogame_arena — anti-fragmentation buffer”
  • Arena(pixels) · .alloc(nbytes) -> memoryview · .canvas(w, h, transparent=None) -> Canvas · .reset() · .free() -> int. Grab one big buffer up front, hand out slices. See MEMORY.md.

picogame_scene — declarative level loader

Section titled “picogame_scene — declarative level loader”
  • load(pg, scene, display=None, strip_h=24, font=None, bank=None) -> View — build a scene from a baked SCENE dict.
  • load_bank(pg, bank) — build a shared asset bank once (reuse across levels).
  • View: .tile_xy(px, py) · .group(tag) · .point(name) · .in_zone(x, y, tag=None) · .is_solid(tx, ty) · .tile_has(tx, ty, prop) · .play(sound_id) · .tick(dt). See SCENE_FORMAT.md.