The hidden game became a project of its own.
I added a small popcorn-catching game as an Easter egg. It was fun to work on, so I kept going. The game
now has two modes, saved records, controller support, analytics, and public leaderboards.
A continuous update and render loop handles movement, collisions, projectiles, power-ups, difficulty,
pausing, and local statistics. Standard and Hardcore modes use the same core systems but apply different
rules when the player misses popcorn or takes a hit.
Input took more work than I expected. Keyboard, pointer, and gamepad controls each behave differently.
The controller code filters out stick drift with a dead zone. If the active controller disconnects, the
game pauses instead of leaving the player stuck in a live run.
Leaderboards without a login screen
Requiring accounts would have been too much friction for a small browser game. The browser keeps an
anonymous player ID and the name the player entered. The Worker validates names and scores before they
appear on the daily or all-time boards. After a run, the game can also show the scores directly above and
below the player.
The public boards introduced backend problems the original game did not have. Scores need server-side
checks, names need moderation, old runs need migrations, and ties need consistent ranks. I added rate
limits, replay protection, score receipts, profile-based renaming, and daily and all-time views while
keeping the player flow short.
Measure before optimizing
As the game grew, guesses about performance became less useful. I built 25 deterministic benchmark
scenarios, from an empty scene to extreme entity counts, and compared changes against the same workload.
I kept the faster changes and rejected optimizations that moved work around without helping the cases
players actually reached.