Match-3 is deceptively hard to make feel good. My first AI version detected matches and removed gems instantly, so the board just blinked and refilled with no sense of chain reaction. Dead.
The naive prompt never mentioned the resolve sequence, so there was no gravity animation, no cascade, no escalating feedback on chains. I rewrote it to specify the full match-resolve state machine with timings, plus a per-cascade escalation of the juice so a big combo feels like a big deal.
No answers yet. Sharing because the resolve-sequence breakdown took me a while to get right.
Build a match-3 puzzle game in a single HTML canvas file, vanilla JS, 60fps. 8x8 board of 6 gem colors, swap adjacent gems by click-drag, only allow a swap if it creates a match of 3+, otherwise animate a swap-and-swap-back.
Implement the match-resolve loop as an explicit state machine with these phases and timings:
1. SWAP: animate the two gems trading places over 120ms (easeOutQuad).
2. MATCH: detect all horizontal/vertical runs of 3+. Flash matched gems white for 80ms, then a 1.1x pop scale.
3. CLEAR: burst 6 particles per cleared gem in its color; add screen shake scaled to how many cleared at once (cap 8px).
4. GRAVITY: existing gems fall into gaps with easeInQuad, speed proportional to fall distance.
5. REFILL: new gems drop from above the top edge into the empty cells.
6. CASCADE: re-check for matches created by the fall; if found, loop back to MATCH. Each cascade level raises a combo multiplier and pitches the SFX up a semitone.
Escalation: cascade level 1 is subtle; by level 3+ add a brief hit-stop (60ms), a bigger shake, and a floating 'COMBO xN'. Constraints: no input accepted while the board is resolving; guarantee the initial board has at least one valid move and no pre-existing matches (regenerate if needed). Framerate-independent. Diagram the state machine transitions in a comment before the code.