Making Greeble
Greeble is a game I made for the JS13K 2017 Game Jam, an html5/JS game-making competition with a file size limit of 13 kilobytes. This year the theme was ‘Lost’. This is my post-mortem for Greeble.
Play the game: Greeble
Look at my messy code: Greeble Github Repo
Use the graphics and sound boilerplate: JS13K 2017 Kit
What Went Right:
Procedural pixel-art
I follow the pico-8 community and all the cool things they make on twitter. Pico-8 is a fantasy programmable game console for making, sharing, and playing tiny games and other programs. The combination of fast, dynamic fluid motion and crisp pixel drawing is something that’s simultaneously nostalgic and new, and not easy to replicate with the canvas API. I wanted pico-8’s simple yet nimble and expressive drawing API in JavaScript.
A tiny selection of some of the cool stuff Trasevol Dog makes in pico-8:
You can turn off anti-aliasing for image rendering on the canvas and turn off interpolation for scaled canvases, but you can’t turn it off for the canvas drawing API. Even drawing a single pixel on the canvas requires translating the context half a pixel to prevent fractional drawing. I wanted to capture the visual appeal of pico-8’s graphics, and retro pixel-art in general in a canvas-based game. Doing this with hand-drawn pixel-art assets is trivial, but I wanted dynamic lines and fills in code without anti-aliasing. So earlier this year I started playing around with setting data on an 32bit array instead of drawing to the canvas, an idea that came from an older article on fast pixel manipulation.
After discovering this was indeed performant enough for animation, I decided I also wanted indexed-color drawing, and started writing a little framebuffer and graphics API. It’s all Bresenham algorithms, and I couldn’t have made this work without help from this article on Bresenham line drawing detailing the algorithms for multiple drawing primitives.
I chose Richard Fhager’s DB32 palette for its elegance and popularity among pixel artists. It helped make my experiments look less programmer-art-y and this restraint proved useful once it was time to start actually making a game.
Now that most of a drawing API was in place, I set out to recreate a few “tweetcarts”; small tweet-sized bits of code that create a visual effect in pico-8.
Since I was doing all my drawing to a 8-bit array and only using 32 colors, I could quite easily draw to un-rendered parts of the array and composite the parts later, or ‘draw’ game data to other parts of the array, like collision data or collectible items. I took advantage of all of these handy side-effects of the graphics engine in Greeble. Here’s one more codepen showing the state of the engine just prior to JS13k start, with a collision demo:
Sound design
The sound effects and music were designed in Sonant-X, and most of them are actually tiny songs. I took inspiration from how the sounds in the original Super Mario Brothers were designed; they’re not one sound, but a series of square or saw wave tones played in rapid succession. There are numerous youtube videos illustrating this idea, even transcriptions of sound effects into sheet music.
Here’s some of the sounds from Greeble, in the Sonant-X Live Editor:
Atmosphere and Feel
Once I had solved my rotation-drawing bug in week 3, the feel of helplessness and despair at the beginning of the game really started to come together. I received great feedback from screenshot posts showing the poor head tumbling around. The rotated-sprite drawing also allowed me to easily create the opening scene where you fall to a pile of trash and robot heads. From there everything came together quickly; the title screen showing the robots drive by, the explosion and fall when you begin, the music was changed-up to be slower and help evoke the feel of being lost. I’m very happy with how the game’s music and opening sequence turned out, and I’ve never previously tackled such an ambitious project.
What Went Wrong:
Game Scope
The game’s scope got away from me a bit. I had this elaborate idea for the theme immediately and just started coding the room system, bitmap collision, and the part-collection mechanic without giving much thought to how much time I would need to actually create content for the game. Once I realized that what I was making was basically a metroidvania and I only had 4 days left, I had to force myself to scale it back, make sure that you could experience an abridged version of this genre inside of the 3-5 minutes most of the judges are going to spend playing. This article on crafting metroidvanias proved most helpful in helping me wrap my head around what works, what makes this genre fun, and how to boil down the experience to something playable in 5 minutes.
Collision Bugs
I had initially wanted to be able to roll around in Greeble. The player character even kept his uni-wheel design through the finish of the jam, although you can just fly around once you have it. That was admittedly just a kludge since I ran out of time to deal with slopes not working. I spent a week on and off dealing with this, trying to solve all of the edge cases, almost to disastrous effect. One of these bugs reared it’s ugly head during Jupiter Hadley’s play-through. Instead of working out what was causing a few edge cases, I decided to simply carve out out part of the room if collision resolution fails. It worked most of the time, and the game features terrain destruction anyways so I let it go. I was incredibly fortunate that Jupiter decided to re-load and have another go at it.
Time Management
I didn’t get to a state where everything was working well enough to design actual world content for the game until about 3 days before the deadline. Almost no time for playtesting or room/level design tweaks, or game content polish. Next year I’ll try to have the game playable much earlier in the jam, and ditch ideas that aren’t working sooner (slopes) and pivot, rather than grinding away at a difficult problem indefinitely.