2021: a Space Opera | a JS13KGAMES 2021 post-mortem

This year was the 10th anniversary of JS13KGAMES, and my 6th consecutive year participating in this month-long competition to craft a game with web technologies within a 13kb ZIP limit.

This year the theme was Space. I made 2021: a Space Opera, a musical puzzle game where you bring harmony to the Cosmic Microwave Background Noise of the universe by arranging planet rings to recompose classic sci-fi songs.

It placed 56th overall, 12th in the Mobile category, and holy moly was I not expecting this, 1st in the Web Monetization.

Try it on JS13KGAMES or on my personal website, and read the past postmortems of my previous entries Blade Gunner (2016), A Tourist In Paris (2017), SUBmersible WARship 2063 (2018), Don’t Look Back! VR (2019) and Highway 404 (2021)


As I was catching up on the last Neon Genesis Evangelion movie, I saw the Door of Gulf and thought: “wow, that looks cool, like Saturn with neon rings… I bet I could make it sound cool too!”.

The Door of Gulf in Neon Genesis Evangelion, or Saturn with neon rings?

And the idea for 2021: a Space Opera was born: each planet’s puzzle is the main musical phrase of a classic sci-fi theme (think Star Wars, Star Trek, etc). The difficulty of each puzzle is measured by the number of notes in the phrase. An instrument plays the notes over and over, but more than half of them start out of order, turning the phrase dissonant. The player must rearrange the notes by ear and/or by visual cue to compose the phrase again, and bring harmony to the planet.

Visual style

I tried to stick very closely to the Evangelion reference shot. Each note is represented by a ring depicting its main traits visually: pitch, length, and delay till the next note.

A note’s pitch is mapped to the Hue component of the HSL colour system and used as its ring colour. When a note plays, the Luminance of its ring colour increases to 90%. The length of each note is both the ring’s width, and the time it takes for the Luminance to fall back to its default 50% value, as the note fades away. The time delay until the next note represents the space between 2 rings.

When the player’s pointer moves over a ring, the default cursor turns into a hand to indicate the ring can be grabbed. When a player clicks, the hand turned into a closed hand, indicating the ring has been grabbed and can be dragged around (unfortunately, touch control on mobile does not provide the opportunity to show such cues). As a ring is dragged over other rings, their colour’s Saturation and Luminance increase to 90% each, indicating the ring can be dropped, and swap position with the ring underneath.

Spoiler alert

The game’s setlist consist of the following 8 themes:

  1. 2001: a Space Odyssey (5 notes, only 2 out of order to serve as a tutorial)
  2. Star Wars: the Force (7 notes)
  3. Star Trek: the Next Generation (7 notes)
  4. Lost in Space (8 notes)
  5. Star Trek: the Original Series (8 notes)
  6. Battlestar Galactica (9 notes)
  7. Galaxy Quest (9 notes)
  8. Star Wars: Darth Vader (9 notes)

What went right

Customizing a music tool, vs starting from scratch with Web Audio

I opted to use a piano for its ability to instil nostalgia in any theme, as demonstrated by the teaser trailer of Star Wars: Rogue One.

The 2nd puzzle is literally the first few notes of this teaser trailer.

Given notes would be reordered during each puzzle, I needed to be able to play notes one by one, so music trackers such as Soundbox or ZzFx Music were ill-suited. I gave Web Audio a try but quickly hit a wall: I wanted to play some notes on a piano, but Web Audio needed frequencies for each millisecond to make the appropriate “beep”. Something was missing in the middle to translate one level of abstraction into the other. And this involved oscillators, instrument envelops, and the mathematics to turn those into a series of frequencies.

Fortunately Crystal Parker, another contestant, had deciphered just enough of Maxime Euzière’s miniSynth code to be able to do just that. In essence, the code starts by initializing 10 audio contexts, so up to 9 notes can still be slowly fading out while the 10th one is played. An audio buffer is associated to each note and filled with the corresponding audio frame data. Notes are represented by their piano key index (0–35) and converted to the appropriate frequency. The piano covers the range C3 (130.81Hz) to B5(987.77Hz). The function generating audio frames (think which frequency at what millisecond) contains the formula for an oscillator sounding like a piano and the envelop of each note (broadly speaking, how quickly the sound maxes out, and how fast it fades out over time). When it’s time to play a note, its audio buffer is connected to the next available audio context.

The improvement I made was to cache the audio frames of each note, in case the same piano key & note length appeared in another puzzle, which shaved off a couple of seconds when the music is generated on game load.

Play testing

I’ve always developed the past games in a silo. Once released into the wild, it was usually a hit-or-miss whether players understood the controls and game objectives as I had intended them.

This year is the first time I involved friends and other participants prior to submitting my entry. This strategy served Rémi Vansteelandt well in 2020, allowing him to win 1st place in the Overall, Mobile and Web Monetization categories with an extremely polished and fine tuned Ninja vs Evil Corp.

On a smaller scale, it allowed me to uncover:

  • bugs (particularly with drag’n’ dropping rings on mobile device)
  • lack of intuitiveness with the visual representation of notes and how to interact with them.

This led to the addition of different CSS cursors to indicate which actions were available or undertaken. I was also able to iterate with the visual semantics of notes, and pick the option that worked best.

Pointer change when hovering and dragging a ring

I started with variable spacing between notes, each equal to the delay till the next note is played. That made notes playing in rapid succession trickier to grab as they were tightly grouped together. When a ring changed place, it also led to all the rings shifting around instantly (I didn’t code any animation). It made it harder to understand what happened (even though it was correct). I ended up using fixed spacing, so moves were more predictable and visually stable.

Variable spacing made short (narrow) notes hard to grab or drop onto.

Speaking of moving a ring, I started by inserting it at the location it was dropped. All the rings between the old and new position would shift by one space towards the old location. I thought it would help the player preserve a partial sequence of notes they had managed to recompose. But a whole lot of colours changed place at once and was hard to understand. I ended up swapping position of the ring that was dragged with the one it was dropped on, thus limiting the number of visual changes.

Shifting ring positions on the left, swapping ring positions on the right.

I also toyed with swapping only the pitch between 2 notes (just their colour) and keeping their duration and delay in their original place. Not only was it harder to guess the musical phrase by ear, it caused too few visual changes and misled the player to think that nothing had happened. I did not keep this experiment, and swapped all the properties of the notes around.

Finally, I experimented with the colour range: At first, I mapped the entire piano key range (0–35 keys) to the full Hue spectrum (0–360 deg aka blue to green to yellow to red). With note colours being constant across musical puzzles, it allowed the player to build a visual memory of what each colour sounded like. But that led adjacent notes to be too similar, while colours at the extremity of the Hue spectrum ended up never used.

Piano keys range on the left, puzzle notes range on the right. First 3 notes are more similar in colours on the left than on the right.

I ended up mapping the range of piano keys appearing in each musical phrase (e.g. 5–17) to the full Hue spectrum. It meant no note would look the same across musical puzzles, but at least adjacent notes were easier to tell apart and made each individual puzzle easier to solve.

Web Monetization

Coil subscribers get exclusive markers under each ring indicating if notes are correctly placed or not.

At first, I was shocked at winning 1st place with something so trivial. I thought it made the puzzles too easy to solve, but I couldn’t think of anything better. However, after reading the feedback left by other participants on my entry during the voting period, I came to realize this helped folks who didn’t guess the movie from the hint given (most of the classic themes I used are getting old and betray my age), or the ones who guessed the movie but didn’t remember its main musical themes. Instead of feeling stuck and frustrated, the markers allowed them to quickly complete a problematic puzzle by trial-and-error, and move on to enjoying the rest of the game.

What went wrong

The game that wasn’t, or Fighting against the theme

When the “Space” theme was announced, I immediately regretted shoehorning my shoot’em up idea into Gamedevjs 2021’s “Mirror” theme back in April, as it was ill-fitted then, and a far better match for JS13KGAMES 2021. However, I lacked the will to continue exploring this game idea.

Unlike previous years where I would only start coding once I had formed a fully fledged gameplay idea suiting the theme, I gave myself permission to experiment, and got quickly obsessed with paint spatters which, if kept on a separate layer, could be combined with the game canvas in interesting ways:

Proto-Splatoon on the left, Proto-INK on the right
  • CanvasRenderingContext2D.globalCompositeOperation’s “source-in” mode would reveal the level map only where paint had been spattered, very much like Zach Bell’s INK, but I felt uncomfortable reproducing the perfectly balanced gameplay of this inexpensive indie platformer without the creator’s consent.
  • Rendering the paint layer on top of the level map would achieve a cheap Splatoon 2 effect. Counting the number of pixels of a certain colour on the paint layer, and dividing by the total number of pixels produced the % of space captured.
I’ve kept using splat instead of spat until I wrote this postmortem :(

Though the top-down prototype looked good, this idea turned impractical for the following reasons:

  • it only worked well on a completely flat map, which isn’t particularly thrilling, and would become more complicated to achieve once I would introduce the upper and lower platforms that made Splatoon maps so enjoyable.
  • Splatoon is first and foremost a multiplayer game. Its solo mode seriously lacks luster. My calculation of the percentage of space captured was canvas-based (aka client-side based), so I couldn’t enter JS13KGAMES’s Server category. That meant AI bots to fill in for human players, and as I learned during JS13KGAMES 2018 with Submersible Warship 2063, AI is hard. I wasn’t willing to try my hand again at this yet.

It was apparent I had no plan for a satisfying gameplay, yet I kept going down that path for longer than I should have, wasting 14 of the precious 30 days allotted.

I seriously considered dropping off the competition and giving up on this year’s t-shirt, when I took a gambit with a musical puzzle game (combining 2 areas I’m a complete novice in). This ultimately paid off, but I must improve my ideation pace so I can dedicate more time to a game with ambitious goals next year.

Personal favorites

The visuals look professional and very consistent. My kids ended up solving a bunch of levels with me as I was voting, a clear sign the gameplay is appealing.

The black & white, subtly dithered graphics are out of this world. The tubular space station reminds me of the ark ship in Knights of Sidonia.

This space station simulator in CSS3D is a technical feat. I would never have imagined it was made of Divs and other DOM elements. Unlocking new building blocks by mastering one game mechanic after another is a clever idea that kept me engaged a long time.

Another whimsical entry by Ryan Malm. The firework of pixels and sounds when liberating a planet pulled me into this soothing experience.

Bright colours, clear animated pixelart sprites and nice chiptunes strengthen this puzzle game.

Finally a twist on Asteroids that improves the gameplay rather than making it less enjoyable. The tunes are energizing.

Another game where music is central to the gameplay. The beats created with the editor are quite enjoyable!

A revetting story in the vein of H.P. Lovecraft with an engaging ASCII style.

A nightmarish psychological experience with a unique artwork. One of the rare games I had to finish before casting my vote.

Software engineer turned manager and father of four, I create pixel art, video games and visual experiments on the Web.