{Color Sort Puzzle} Project Report
1. The Concept
Color Sort Puzzle is a tap-based water-sort game for phones. Colored liquid sits in glass cups. The player’s job is simple to explain and hard to master:
Tap a cup, then another — pour matching color until every cup is one color (or empty).
It is a classic water-sort loop, but the product identity is Khmer-first casual: the default title is កែវទឹកពណ៌, copy ships in Khmer and English, and the board reads as glossy cups, not a spreadsheet of stacks. The unique hook is the pour itself — a cloned cup tilts, a color stream falls, the target fills — so each move feels like liquid, not a list splice.
Design goals:
- Instant rules (one hint: “Tap a cup with color, then tap its destination”)
- Soft ramp across 100 levels × four difficulties (Easy / Medium / Hard / Expert)
- Beginner tools (undo, hint, extra cup, Level 1 hand tutorial) with enough mix depth for longer sessions
- One clear win loop: sort → celebrate → next level
- A smartphone game UI (one job per screen), not a web dashboard
Risk/reward sits in the tools and the economy: hints and extra cups are limited per level; coins fly home when a cup completes; stars grade how clean the solve was. Daily Challenge adds a reason to open the game again tomorrow.
2. The Stack
Built as a zero-build, zero-dependency product so it can ship and play the same day.
Layer Choice ----------- ---------------------------------------------------------------- Structure index.html (screens: loading, home, levels, game + overlays) UI Vanilla CSS (CSS variables, 6 themes, mobile-first, safe-area) Logic Vanilla JavaScript ("use strict", ~1,500 lines) Art CSS cups + liquid layers; sprite sheet assets/ui-icons.png Audio Web Audio API (procedural SFX + win fanfare; no sound files) Progress localStorage (cups-water-sort-v1) — per-difficulty progress, coins, theme, language, tutorial flags, daily key Target Phone browser / PWA-style viewport (portrait, user-scalable=no) Fonts Nunito + Noto Sans Khmer (Google Fonts)
No framework, no bundler, no npm — open the folder and play.
Architecture choices: difficulty tables (DIFFICULTIES) sit apart from pour logic; levels are seeded so the same number always deals the same board; UI strings live in a TEXT.km / TEXT.en map. Design constraints live in sakurai/ and rules/ (Khmer UI / game-design notes), not in a separate engine.
3. The 1 Day Sprint (+ polish pass)
The day was treated as a full vertical slice: concept → playable core → polish → shippable demo. Scope stayed tight: one mechanic, one visual world, one progression path. Anything that did not serve “pour colors until the cups are clean, and feel good doing it” was cut.
Morning (Hours 1–3):
- Locked the fantasy: glass cups, glossy color bands, forest-green default skin — a phone puzzle, not a lab sim.
- Built the app shell: loading splash, home (PLAY + Daily / Levels / Themes), level grid, in-game HUD.
- Defined core constants: capacity 4, color palette, 100 levels, four difficulty curves (colors, empty cups, coin bonus).
- Implemented selection → pour rules (
topRun,canPour,pourAmount) and cup rendering. - Got a first playable loop on device: tap source, tap target, stacks update.
Outcome: A clickable prototype that already felt like the game, not a wireframe.
Afternoon (Hours 4–6):
- Added seeded level generation (stable boards per level + difficulty) and a swap so no cup starts already solved.
- Wired progress: Play / Continue, unlock persistence, undo, restart, pause / home, per-difficulty save.
- Built tools with limits: 2 hints, 1 restart, 1 extra cup per level — so help is a choice, not infinite undo.
- Started juice: cup lift, pour clone + tilt, color stream, fill, complete-cup highlight.
- Added coin fly from a finished cup to the header (+5 per tube) and a star rating on win.
- First Web Audio pass (tap, invalid, pour, win melody by star count); vibration on bad pours.
Outcome: A real campaign, not a single hand-made puzzle.
The Finish Line (Hour 7-8):
- Finished win / replay / next / home flow, confetti, and Level Complete stats (moves + coins).
- Daily Challenge (date-seeded expert board) and theme picker (Classic, Sunset, Ocean, Forest, Night, Candy).
- Khmer / English toggle; Level 1 guide + pointing-hand tutorial so the first pour is taught, not guessed.
- Board scaler so 5–16 cups still fit a phone; safe-area padding; reduced-motion fallback.
- Pass for readability and “open file → play” confidence.
Outcome: A self-contained demo ready to show, share, or iterate.
Polish (Aug 10):
- Hardened pour geometry: rotate around cup center, place the mouth above the target, keep the body on the source side so liquid does not “teleport.”
- Smoothed coin arcs (bezier, stagger, header pulse) so rewards read as fly-in, not pop-in.
- Icon sprite sheet (
ui-icons.png) for coin, lock, trophy, tools, settings — one asset, many buttons. - Theme tokens (CSS variables) so one skin change recolors buttons, panels, and accents without restyling every screen.
- Copy and layout pass against sakurai/rules: one action per screen, 3D game buttons, Khmer-safe type.
- README-free “just open index.html” still holds; design notes stay under
sakurai/andrules/.
Later polish (Aug 18) stayed in the same spirit: Level Complete badge restyled to LEVEL + number + difficulty chip; level-grid stars swapped from ★ text to the gold star sprite; Play button sparkles kept, shake/jelly motion removed after it felt ញាក់ៗ (jittery).
4. The Roadblocks
- Pour that reads as liquid — Early moves updated the stack instantly. A convincing pour needed a cloned cup, tilt math (
getPourPose/ mouth alignment), a falling stream, and drain/fill timing. Overflow:hidden on the wrong parent clipped the 3D button shadow and the stream; layers had to stay outside the board.
- Feel vs. motion noise — Scale-pulse, bounce, and ripple on PLAY all fought the 3D bevel and looked cheap or shaky. The fix was not “more animation”: keep the button still, twinkle sparkles only. Same lesson as coin fly: extra transform on a beveled control reads as ញាក់ៗ.
- Many cups, one phone — Expert boards grow color count and cup count. Fixed sizes overflowed; a board scaler (
fitBoard) and clamp() cup sizes kept tap targets usable.
- Audio without assets — No sound pack in a 1-day sprint. Web Audio synthesis had to carry taps, errors, and a star-scaled win fanfare; browsers still need a user gesture to unlock the context.
- Two languages, one layout — Khmer glyphs need Noto Sans Khmer and more width than English “PLAY” / “LEVEL.” Pills, badges, and buttons had to flex without breaking the home top bar.
- Scope pressure — Shuffle-as-a-shop, ads, accounts, and a real solver were tempting. Seeded shuffle + a monochrome swap kept boards mixed enough for a day; a full
isSolvablesearch was cut so the loop could ship.
- Progress without a backend — Four difficulties × 100 levels, coins, stars, and tutorials all live in one localStorage blob, including a migration from an older single-progress save. Save-key and shape had to stay boring and backward-friendly.
5. Key Takeaways
- One sentence concept + three static files is enough to ship a complete 100-level × 4-mode loop in a day.
- Familiar rules (water sort) + a local identity (Khmer-first, cup pour, theme skins) beats inventing a new mechanic under time pressure.
- Feel is product: pour timing, coin arcs, and a still Play button with sparkles mattered as much as
canPourfor “this is a game.” - Motion that scales or hops a 3D button often looks cheaper than decoration that sits on top of it.
- Cut features early; polish the core loop (pour → complete cup → next) instead of spreading thin across meta systems.
- Design docs upfront (
sakurai/,rules/) kept screens honest: one job, portrait, smartphone — not a dashboard.
My final thought:
A one-day game only works when the concept is a single sentence and the stack stays out of the way. Color Sort Puzzle proves that: tap, pour, sort; Khmer on the home screen; a full campaign with tools, coins, daily play, and six skins inside three files. The next steps are optional — a real solvability solver, handcrafted early levels, richer audio — but the core already delivers what mattered most: pour the color, see the cup lock, smile, next.