I hadn't built a game since my Flash and ActionScript days, almost 20 years ago - Flash quietly died out of the industry not long after Apple refused to support it on iPhone. My 10-year work anniversary got me thinking about what I actually had to show for two decades in web design: hundreds of sites for agency clients, most of them probably rebuilt or replaced by now, and increasingly narrow slices of work: a button colour here, an internal intranet tweak there, nothing really mine.
So I decided to just build something. A little shoot-'em-up in JavaScript, for fun, for myself: partly to flex the design and coding muscles agency work rarely used, partly because I'd been paying for web hosting I wasn't using for years.
It started as a single HTML file with no build step and no version control, called OUTRUNNER. Within a day it already had the bones of the game it would become: four power-ups drifting in as icons, a mini-boss, a two-track soundtrack that crossfaded. By the end of that same day it had the name that stuck, Neon Skies, and a full day/night cycle timed to the music.
A few early instincts shaped everything after. Power-ups became hit-based instead of timer-based: your Spread Shot or Shield doesn't wear off on a clock, it lasts until you take a hit. Hull and lives got split apart, so running out of hull costs a life and refills the bar rather than ending the run outright. The underlying idea was always the same: let the player's skill decide when things run out, not a countdown.
The biggest rebuild came when I noticed wave progression - originally tied to score - let players farm points forever by dodging bosses and grinding easy kills, which is a real problem once you're putting a leaderboard in front of people. I replaced it with a fixed, deterministic enemy roster per wave, so score and wave-reached actually mean the same thing for every player, and added a Perfect Clear bonus to make fighting properly worth more than dodging past everything. The weapon system got the same overhaul, from a single replace-on-pickup slot into a held roster you level up and cycle between, with two new weapon types, Pierce and Chain, built to cover distinct threats rather than being reskins of what already existed.
Some of the hardest bugs weren't new features at all - they were the same bug shape reappearing in different bosses. Something's position kept getting computed from an absolute elapsed-time value instead of an accumulator that only advances while it's actually supposed to be moving. Pause a boss mid-animation, resume it, and whatever was still silently ticking in the background would cause a visible jump. It hit the Snake boss twice and the Sentinel once before I started treating it as a standing thing to check for on any new timed motion, the kind of lesson you only really learn by tripping over it repeatedly.
Getting it out the door meant a real PHP/MySQL leaderboard once I confirmed the hosting could support it, re-encoding the music to cut bandwidth, and a minify-and-verify pipeline so I'm never uploading untested code. And it didn't stop at "done": player feedback since launch has fixed a render loop that was needlessly maxing out high-refresh monitors, and a real bug where typing a space into your leaderboard name would silently restart the run instead of submitting your score.
You can play it yourself at ohmikey.co.uk/neon_skies, or check out the full how-to-play guide for the weapon, boss, and scoring breakdown.