Building a Snake Game for My Site

The Games section of this site has been sitting there quietly with exactly one thing in it for a while now, so I figured it deserved a proper writeup. Snake โ€” yes, that Snake โ€” is now live and playable right in the browser at cainenielsen.com/games/snake.

Why Snake

Every developer eventually builds Snake. It's the "hello world" of game programming: small enough to finish in an evening, but with just enough moving parts โ€” game loop, input handling, collision detection, state management โ€” to actually be worth building instead of just following a tutorial. I wanted something fun to drop into the Games section of the site that didn't need a backend, a database, or anything beyond the browser itself, and Snake was the obvious answer.

The core loop

At its heart, Snake is a surprisingly clean state machine running on a fixed tick:

  • A grid, with the snake represented as an ordered list of coordinates
  • On every tick, a new head is computed in the current direction of travel and pushed onto the front of that list
  • If the new head lands on food, the tail stays put (the snake grows); otherwise the last segment is popped off (the snake just moves)
  • Every tick checks the new head against the walls and against the snake's own body โ€” either one ends the run

That's genuinely most of the game. The rest is UI: rendering the grid, tracking score, listening for input, and handling the win/lose states cleanly.

A few things that were more interesting than expected

Input buffering. The naive version of "listen for arrow keys, update direction" has an annoying bug: if you press two directions in the same tick (say, down then left, in rapid succession), the snake can be told to reverse directly into itself before it's had a chance to actually move. The fix is to buffer the most recent valid input and only apply it at the start of the next tick, rejecting any direction that's the exact opposite of the snake's current heading.

Keeping it playable on mobile. Since this lives inside the same Nuxt/Vue site as everything else here, it needed to work reasonably well on a phone, not just a keyboard. Arrow keys are easy; swipe gestures on a touch screen are not quite as trivial โ€” you need a minimum swipe distance and a dominant-axis check (was this swipe more horizontal or more vertical?) before you can confidently translate it into a direction, or small, unintentional touches turn into random direction changes.

Tick rate as difficulty. Rather than hardcoding a single game speed, the tick interval shortens slightly as the score climbs. It's a small touch, but it turns a technically-simple game into one that actually gets harder to play the longer you survive, without needing any extra game design beyond "make the loop run a little faster."

Where it fits

This was never meant to be a flagship project โ€” it's a fun, self-contained toy sitting inside the personal site alongside the blog and the project writeups. But it scratched an itch: sometimes the most satisfying thing to build isn't the architecturally interesting backend system, it's a tight little game loop that's fun to poke at on a break.

As always, thank you for reading. I really appreciate it. ๐Ÿ’–