← all work
LiveiOS Game · Solo-built

Snek Snacks

Classic snake, re-engineered — a frame-perfect arcade core wrapped in a 90-card collection gacha.

90
collectible cards across an 18-stage gacha
32
unit tests, zero analyzer warnings
100%
of art & chiptune audio procedurally generated
~4.9k
lines of Dart, designed & built solo

Overview

Snek Snacks reimagines the arcade classic with a modern engine and a collection meta. The core is a framerate-independent fixed-timestep simulation hardened against app-backgrounding: the snake body is an O(1) set-backed structure with a correct tail-chase collision waiver (the edge case most clones get wrong), growth is modeled as debt so power-ups extend you gradually, and the board expands rightward without remapping a single coordinate.

On top sits an 18-stage, 90-card gacha that awards a weighted-random card per qualifying run and unlocks cosmetic snake colors as stages clear — with the entire unlock schedule regenerated deterministically from a single persisted seed. Monetization is a mature AdMob layer, telemetry runs on Firebase Analytics, and every card, sprite, app icon, and chiptune track is generated by a standalone Python pipeline.

Full stack

  • Flutter · Dart 3 · Flame 1.37 (FlameGame, components, overlays)
  • flutter_soloud (BGM + SFX mixer, real-time pitch sync)
  • google_mobile_ads (banner · interstitial · rewarded)
  • Firebase Core + Analytics (GA4 funnel events)
  • games_services (iOS Game Center leaderboard)
  • shared_preferences (high score · gacha state · settings)
  • dart:ui Canvas procedural pixel-art rasterization
  • Python 3 · Pillow · numpy · ffmpeg (offline asset generation)

Engineering highlights

The parts a code review would find interesting.

01A snake engine that's actually correct

The body is a ListQueue for ordered traversal plus a parallel Set for O(1) collision membership, kept in sync at every move. A single "will the tail move this tick" boolean drives both tail removal and the collision waiver, so chasing your own retreating tail is correctly safe — the classic snake bug, eliminated and unit-tested.

02Frame-perfect and backgrounding-proof

A fixed-timestep accumulator decouples simulation from render framerate, every time-accumulating clock is dt-clamped, and the lifecycle auto-pauses a running game — so returning from the background never teleports the snake into a wall. A whole bug class designed away.

03Seed-only gacha persistence

The full color-unlock schedule across all 18 stages is never stored; it is regenerated deterministically from a single integer seed via a constraint-satisfying permutation generator (no color repeats within a category, distinct per stage, with restart fallback) — an elegant space and migration win.

04Live-ops monetization done right

AdMob banner, interstitial, and rewarded video with mature UX idioms: rewards fire only after the ad is dismissed (never under it), and a suppression window prevents jarring back-to-back ads while still surfacing the owed interstitial. Frequency capping survives app restarts.

05Audio that tracks difficulty

BGM playback rate is synced to game speed every tick via SoLoud's setRelativePlaySpeed (with a dead-band to skip redundant native calls), so the chiptune pitch rises smoothly as the snake accelerates — plus voice protection so SFX floods can't evict the music track.

06Procedurally generated everything

A standalone Python pipeline synthesizes all 90 cards from a composable pixel-creature engine, the app icon, sprites, and seamless-looping NES-APU chiptune BGM and SFX. The build never touches Python — only the baked assets ship.