Heads up — Pico-8 costs $15. It's the only paid tool we recommend in any walkthrough on Pixeldex, and it's a one-time purchase (no subscription). If you don't have it yet, check the cost guide for context. The rest of this walkthrough is $0.

What you'll build

Total ~150 lines of Pico-8 Lua. The whole thing fits comfortably in Pico-8's token budget.

What you need

How to use this guide

Pico-8 has its own integrated editor. We'll write Lua in there, draw the sprites in Pico-8's sprite editor, and stay inside the Pico-8 environment for everything except the Claude prompts. Each step has a single Claude prompt and a deliverable.

HOUR 01 ~60 min

Sprites and grid renderer

Open Pico-8. ESC to flip between code and sprite editor. Press F4 to enter the sprite editor.

Draw 4 sprites in the first 4 slots (sprite indices 1, 2, 3, 4):

  • Sprite 1: player. A simple 8×8 character. Color suggestion: green (color 11) on transparent.
  • Sprite 2: wall. A solid block with subtle texture. Purple (color 2) is good.
  • Sprite 3: box. Wood-tone block. Orange/brown (color 9 or 4).
  • Sprite 4: target. An empty outlined square or X marker. Mint/cyan (color 11 or 12).

Make sprite 1 (the player) have transparent background — color 0 is the default Pico-8 transparent.

Now ESC back to the code editor and send Claude:

$ Build me a Pico-8 grid-based puzzle game scaffold.

// shape
- The level is a 2D table 'grid' where each cell is one of: 0 (empty), 2 (wall), 3 (box), 4 (target).
- Player position is stored as (px, py) tile coordinates, separate from the grid.
- Grid is 10 wide x 8 tall, drawn at offset (24, 16) so it's centered.

// _init
- Define a small starter level as a table of strings (e.g. "##########", "#.....p..#", etc) where # = wall, p = player, b = box, t = target, . = empty.
- Parse it into the grid + (px, py).

// _draw
- cls(0) for black background.
- Draw HUD at top: "LV 01" left, "M:0" right (move counter, starts at 0).
- For each grid cell, call spr() with the appropriate sprite index at the cell's pixel position.
- Draw the player sprite at (px, py) in pixels.

// _update
- Empty for now (we'll add input next hour).

// constraints
- Single Pico-8 Lua block. Keep under 200 tokens for the scaffold.
- No globals beyond grid, px, py, level, moves.

// return format
- One .p8 lua block of code.
- A separate small block showing the starter level string table.
- No prose before or after.

Paste into Pico-8's code editor. Ctrl+R to run. You should see your sprites laid out as a grid — walls around the edge, the player somewhere inside, maybe a box and a target.

End of Hour 1: a static level renders with all four sprite types.

HOUR 02 ~60 min

Player movement on the grid

Send this prompt:

$ Extend _update to handle grid-based player movement.

// movement
- On btnp(0) (left) / btnp(1) (right) / btnp(2) (up) / btnp(3) (down), attempt to move the player one tile in that direction.
- Compute target_x, target_y for the destination.
- If grid[target_y][target_x] is a wall, block the move.
- If the destination is empty (or a target tile, since target is walkable), accept the move and increment moves.
- If the destination has a box, check the cell beyond the box. If THAT cell is empty (or a target), push the box: clear the box's old position, place box at the new position, advance player. Increment moves. Else, block the move.

// constraints
- Single _update function. No coroutines.
- Use btnp (button press, fires once per press) not btn (held).
- Keep token cost low.

// return format
- Updated _update function only, in a code block.
- No prose before or after.

Replace your _update. Run. Arrow keys should move the player one tile at a time, blocked by walls. Walking into a box pushes it (if there's space behind).

End of Hour 2: a working playable Sokoban-style mover.

HOUR 03 ~60 min

Targets, win condition, and 3 levels

Send this:

$ Add targets, a win condition, and three levels.

// targets
- The grid stores tiles as a number per cell. Targets must persist when a box is on top of them.
- Refactor: each cell has TWO layers — base (empty / wall / target) and top (box / nothing). Use two parallel grids: base[y][x] and top[y][x].
- Player walks on base, can push tops if base behind is walkable and top behind is nil.
- A box ON a target = box visually highlighted. Use spr() for the box but draw a thin mint outline behind it via rectfill or similar.

// win condition
- After each move, count: do all base[y][x] == TARGET cells have top[y][x] == BOX?
- If yes, transition to a "level complete" state: brief flash, advance to next level after 1s.

// 3 levels
- Define LEVELS = { L1, L2, L3 }, each a table of strings.
- L1: trivial (1 box, 1 target, 4 moves).
- L2: 2 boxes, 2 targets, requires planning.
- L3: 3 boxes + a corridor that traps you if you push wrong.
- A level_index variable tracks current level.

// level transition
- On level complete, show "LEVEL CLEAR" centered for 1s, then load the next level.
- After L3, show "YOU WIN — Z TO RESTART" until btnp(4) is pressed.

// constraints
- Refactor minimally — keep the same _init/_update/_draw structure.
- Token budget still under 800 total.

// return format
- Updated full Pico-8 Lua block in one code block.
- No prose before or after.

Paste, run. You should now have three levels with increasing complexity. Solving L1 advances you to L2, etc. Solving L3 shows the win screen.

End of Hour 3: a complete game loop.

HOUR 04 ~60 min

Sound + ship

Pico-8's built-in sound editor (F2) lets you compose chiptunes. For our puzzle game we just need three SFX:

  • SFX 0: a soft "click" for player movement (use the noise instrument, single short note)
  • SFX 1: a "thud" for box push (slightly lower pitch, also short)
  • SFX 2: a "ding" arpeggio for target-completion (3-4 ascending notes)
  • SFX 3: a longer chord for level-clear (5+ notes, mixed instruments)

Authoring SFX in Pico-8 is fast — pick the instrument, click notes on the piano roll, hit play to test. ~15 minutes for all four if you're not picky.

Then send Claude:

$ Wire up SFX into the puzzle game.

// triggers
- On player move (no box involved): sfx(0).
- On box push: sfx(1).
- When pushing a box onto a target: sfx(2) (in addition to sfx(1)).
- On level complete: sfx(3).

// constraints
- Add the sfx calls inline in the existing movement logic. Don't refactor.

// return format
- Just the changed lines, with line context (e.g. "in the 'box push' branch, after updating top[ty][tx], add sfx(1) and conditionally sfx(2)").
- Or the full updated _update function if cleaner.
- No prose before or after.

Apply, run, push a box onto a target. You should hear it.

To export and share:

  1. In Pico-8, SAVE puzzle.p8 in the editor (saves your cart).
  2. EXPORT puzzle.html to make a web-playable HTML build.
  3. Pico-8 also generates a label image — set one with F7 while playing on a frame you like.
  4. Upload puzzle.p8 to the Pico-8 BBS (lexaloffle.com/bbs) for the Pico-8 community, or zip the HTML build and upload to itch.io.
DONE. You shipped a Pico-8 puzzle game in 4 hours.

What to do next

Why this works

  1. Pico-8's constraints are the gameplay. 128x128, 16 colors, integer-grid movement — these aren't limitations to fight, they're the game's vibe. Sokoban-on-Pico-8 looks right because it's already low-resolution and grid-based.
  2. The 4-hour scope means 3 levels. Not 30. Not 100. Three. You hand-author them like you'd hand-author a song's verses, and that's the right scope for this format.
  3. The Claude prompt asks for token-budget code. Pico-8's hard token limit makes terse code a real constraint, and Claude responds well to "keep it under N tokens."

License + sharing

Walkthrough is CC0. Prompts are CC0. The cart you make is yours. If you publish on the Pico-8 BBS, a link to pixeldex.app in your cart description helps the next solo dev find this. No requirement.