Coding into the Void

Coding into the Void

A blog that I’ll probably forget about after making thirty-five posts.

2019 Retrospective: Part 1: From Drop to Drop

A 2019 retrospective… in 2021? It’s likelier than you might think. I’d thought about doing it in 2020, but I didn’t have a blog back then, and events a few months into 2020 took my mind off the idea entirely. I didn’t have any game dev goals in 2020, but I do have one in 2021, and I was just thinking about how that already wasn’t going to plan.

2019 didn’t really go to plan either. My goal was to make 12 games that year, ideally hitting one game a month. I did publish 12 things on itch, although the gaminess and distinctiveness of some of those games were questionable. Regardless, I don’t have any regrets about what I accomplished that year.

First, some backstory. I’d published BinPuzzlin all the way back in 2016, and I’d had a long-running on-and-off (mostly off) project based on Bound or Obstacle type maps for StarCraft that I’d started way back in early 2014. There were some small games and prototypes, like a magnet-based movement prototype inspired by Mistborn in 2016, and a 3D triangle-based ninja game for my nephew in 2017. My track record for finishing games that I’d started was not great.

I wanted to change this and, more importantly, get over my hangups about publishing things to the world.

Games are ordered by when they released, or when I stopped development on them.

The Golden Months

Four Block Drop: Endless Motivation

Tetris is a stereotypical “first game dev project”. I had wanted to play around with web game development, as I had messed around with javascript to create little toys like a mandelbrot renderer on my personal webpage and had fun with the instant feedback that web provides. Phaser 3 seemed like a promising choice, so I set out to investigate that. I also wanted to make a good Tetris game. One that integrated wall kicks, and did spins correctly. I also was hungering for Tetris Effect, which hadn’t been released on PC yet.

My first commit on Four Drop Block was on January 3rd. I ran into a few issues with Phaser (like input not being cleared properly when changing scenes), but everything being code was a comforting return to my days of iOS development, where I’d use percentage-based layouts to place elements on the screen, and I could easily follow how the code interacted, as opposed to Unity’s combination of scripts and hooking things up in the editor.

I remained highly motivated during the whole month, finished the game on January 28th, and published it on itch January 31st. I came back to FBD in both January 2020 and January 2021 (for some reason I have been compelled to come back to it every January), so it looks very different now than it did back then. It’s certainly derivative, but I’m pleased with how well it plays.

What I Learned

  • How to use Phaser 3, and many of its intricacies.
  • All the details that go into a modern Tetris game.
  • Just how much I liked Tetris.

So far, all was going to my plan.

The Walk & Talk: Finding a Path

While I was working on Four Block Drop, I saw, somewhere on reddit, a post about an upcoming game jam: the TV Game Jam. I’d jammed a few times for work before, but nothing on my own. The time schedule was fairly permissive, as the jam gave two weeks to work on the game. It started on February 1st, which both gave me plenty of time to work on my game, but also allowed me to get a head start on my March game.1 It seemed like a perfect fit.

An idea came to me right away: why not base it on one of my favorite TV shows, The West Wing? I was listening to the podcast The West Wing Weekly at the time, and I remembered them talking about the difficulty of movement for the camera crew when filming some of the walk and talk scenes. I was enthralled by the idea: you have to keep the actors in frame as they move through a set of The West Wing, and as an added complication, sometimes you need to make sure other entities aren’t in the scene. For extra fun, you can film through windows as well.

I started right when the jam did—February 1st. Things went smoothly. I used Phaser 3 again, and found some code online to compute visibility based on polygons and extended it to hackily support arcs, which saved me a great deal of time over coding it myself. I stood up a prototype quickly (available in game as a bonus scene), and was able to get mechanics that felt relatively well.

There were two big drags on my productivity and motivation this jam.

The first was constructing the set itself, and it involved placing walls, doors, and windows by hand, tweaking the raw numbers as I went. To give an example of how tedious it was, here’s the final code for constructing the press secretary’s office (note that this is simplified from how I was first doing it):

// CJ's Office
scene.addText(  59, 413, "Press\nSecretary", 30)
scene.addCWall( 18, 332,  68,  true, true, [D.c(44, DoorDir.DownRight)])
scene.addSWall( 82, 336,  SW,   16);
scene.addSWall( 18, 374,  20,  WW);
scene.addSWall( 32, 380,  WW,  14);
scene.addSWall( 26, 388,  WW,  58);
scene.addSWall( 32, 440,  52,  WW);
scene.addSWall( 84, 440,  WW,  44);
scene.addSWall( 90, 478,   4,  WW);
scene.addCWall( 86, 348,  56, true, true, [D.c(19, DoorDir.DoubleUp)]);
scene.addCWall( 86, 352,  90, false, true, 
                  [D.c(2, DoorDir.LeftUp), W.c(27), W.c(43), W.c(59)]);
scene.addCWall(130, 352,  40, false, true, [D.c(2, DoorDir.RightUp)]);
scene.addCWall( 38, 374,  48, true, true, [D.c(26, DoorDir.DownRight)]);

// That really annoying part by CJ's office
scene.addCWall( 90, 423,  54,  true, true, [G.c(12, 32)]);
scene.addCWall(102, 427,  32,  true, true, [D.c(7, DoorDir.DoubleUp)]);
scene.addCWall( 90, 434,  48,  true, true, [G.c(12, 32)]);
scene.addCWall( 98, 427,   7, false, true);
scene.addCWall(134, 427,   7, false, true);

For a bit of context, SWall stands for simple wall, and CWall stands for complex wall (supporting doors and windows).

The second was creating the routes around the levels for the actors themselves. Initially I was placing each node that they walked along by hand, and syncing movements timings to match text time manually. This was an arduous and brittle process. Here’s the code involved for a section of the tutorial, which was done by hand:

scenario.addMessage(Character.DeputyCommsDirector, "You should feel honored.");
scenario.addMessage(Character.DeputyCommsDirector, "It's hard enough to get me out of bed for\nan episode, let alone for someone else's benefit.");
scenario.addMessage(Character.ChiefOfStaff, "Nate's turning blue, which means you'll also need to\nfilm him.", true);
scenario.addMessage(Character.ChiefOfStaff, "The required characters can change over the course\nof a scene.", true);
scenario.addMessage(Character.ChiefOfStaff, "Let's head over to the lobby.");
scenario.addMessage(Character.DeputyCommsDirector, "Now, there are going to be some really \nunphotogenic people wandering around.");
scenario.addMessage(Character.DeputyCommsDirector, "We don't want them to be in the scene.", false, 1000);
scenario.addMessage(Character.DeputyCommsDirector, "Unfortunately, we'll still have to include Chad.", false, 1000);
scenario.addMessage(Character.DeputyCommsDirector, "Anyone in red should not be included in the scene.", true, 1000);

const bill = scene.addPerson(new Path(scenario, 491, 274)
    .addNode(55.65, 497, 337)
    .addNode(0, 455, 370)
    .waitUntil(73.5)
    .waitFor(4.25)
    .waitFor(0, CameraRequirement.Required)
    .waitUntil(77.75)
    .addNode(0, 421, 335)
    .addNode(0, 423, 293)
    .addNode(0, 351, 289)
    .addNode(0, 334, 223)
    .addNode(0, 329, 190)
    .addNode(0, 185, 196));

It’s full of magic numbers and almost impossible to debug, and a chore to implement. I ended up taking a vacation day off of work to work on the movements. The writing came much more naturally to me. I finally bit the bullet and made a node system and an A* implementation to compute paths for me. At the same time, I supported syncing movements to message timings, giving me considerably more flexibility.

// Circle around the bullpen talking to Josh, stopping by to talk to Carol
scenario.addMessage(Character.DeputyChiefOfStaff, "The general theory of relativity.", false, 1000)
scenario.addMessage(Character.PressSecretary, "Isn't that a hundred years old?", false, 1000)
scenario.addMessage(Character.DeputyChiefOfStaff, "Observing gravitational waves is new.", false, 1000)
scenario.addMessage(Character.PressSecretary, "Gravity is new?", false, 500);
scenario.addMessage(Character.DeputyChiefOfStaff, "MJ...", false, 250);
scenario.addMessage(Character.PressSecretary, "It was a joke!", true, 500);
const lynn1 = scenario.addMessage(Character.DeputyChiefOfStaff, "This is important. You should start with this.", true, 1000);
const lynn1e = scenario.addMessage(Character.PressSecretary, "Lynn, those CFPB stats?", false, 500);

// C.J.
const mj = scene.addPerson(new Path(scenario, 54, 424, CameraRequirement.Required)
    .arriveAtNoDelay(lynn1, [[79, 409], [42, 402], [72, 424], [41, 424], [72, 386], [68, 357], Locations.COC])
    .waitUntil(lynn1e)
    .arriveAtAutoNoDelay(lynn2, scenario.graph, [Locations.PBML, Locations.PBLB3, Locations.COC])
    .waitUntil(lynn2e)
    .arriveAtAutoNoDelay(lynn3, scenario.graph, [Locations.RNPS3, Locations.PBB, Locations.PB3, Locations.PBT2, Locations.DCOSI2, Locations.DCOSI1, Locations.PBLUO, Locations.PBMR1, Locations.COUO, Locations.COC])
    .waitUntil(lynn3e)
    .arriveAtAutoNoDelay(ezra1, scenario.graph, [Locations.PBM])
    .arriveAtAutoNoDelay(ezra1e, scenario.graph, [Locations.PBLUO, Locations.BigHUL, Locations.BigHU3, Locations.RLCOSLD, Locations.CoSLO])
    .arriveAtAutoNoDelay(theo1, scenario.graph, [Locations.RLCOSRU])
    .arriveAtAutoNoDelay(theo1e, scenario.graph, [Locations.BigHL1, Locations.BigHL4, Locations.BigHL6, Locations.BigHVT, Locations.CommsCR])
    .arriveAtAutoNoDelay(bill1e, scenario.graph, [Locations.BigHT1, Locations.LobR, Locations.PB1, Locations.PBRE])
    .arriveAt(lynnTalk, [Locations.PBR])
);

With these changes, I could still hardcode positional segments (like I do when wandering around inside a scene), but I could also specify nodes and it would automatically path from one to another. Additionally, I could tie it to specific messages, giving me more flexibility in changing wording without having to redo all the timings. The locations are a mess of initialisms, but it’s commented elsewhere what they map to.

This did introduce its own set of problems—since I had used nodes instead of boxes that the actors could move in, they would all follow the exact same path, which didn’t look great. I wish that I’d instead specified boxes and lines that they had to hit to give it more variability, but that would have taken considerably more time and I was starting to check out on this specific portion of the game.

I finished it on February 14th, around 3 hours before the jam deadline. I am very proud of this one. I think the gameplay concept is relatively unique2 and I liked my attempt at writing facsimiles of West Wing scenes. I did have to compromise to meet the jam deadline. The art is minimalistic,3 the sounds are almost non-existent, and the performance is poor on lower-end machines.

It also has the difficulty of making the user split their attention between the lines of dialogue on the screen and actually following the actors, which makes it exceptionally difficulty to follow. A plus and minus of game jams is that sometimes you realize something just doesn’t work but you have to keep it in because there’s no time to come up with an alternative.

I’d never watched anyone play any of my games before (except in person), and I was very reticent to do so. I would open up a video, and then a few seconds later I’d find that I’d stood up and walked away from the computer without thinking about it. It’s like my body itself was rebelling against the concept. When I actually did find the will to watch it, I was pleased with what people thought of it. I’d added checkpoints (it was trivial to do since all I needed to do was snapshot the player position and the time), and I could see the relief on people’s faces when they realized that losing would set them back a trivial amount of time. Due to low uptake on later games,4 this was the one of two times this year I’d be able to see people’s reactions.

What I Learned

  • Watching people play my work makes me anxious. (Not much I can do with this).
  • That level design (especially level design with poor tooling) drains my soul. This would be the last game this year that I made that had fixed, expansive level(s).
  • That aping a show known for its good writing is almost certainly a mistake, even if I am proud of what I wrote.
  • That I am fully capable of completing a two week long jam myself if I’m focused on it.
  • Sound and visuals are very important, although I still struggle with good audio and visual design today.

The Appeasement of Cyclus: Speed Run

The next game that I finished was one that I began for the Extra Credits Game Jam #3. It had the theme “cycles”. I immediately was captured by the idea of a game where you dodge enemies, but where the timing of everything was governed by wheels that you could see on the screen. I wanted to do something that was reminiscent of very old indie shovelware5 games where it was just dodging enemies, but I wanted to make it polished, fair, and fun to play.

Since this was a 2D game and I had a bunch of recent Phaser 3 experience, I stuck with Phaser 3. This jam had the tightest deadline, clocking in at 100 hours, or just over 4 days. I started work immediately when the jam opened, on February 28th. I used typescript, as I had tried that out for my other project and converted part of The Walk & Talk to it, and it revealed some bugs to me and gave me the explicit types that I crave.

I started on February 28th, the day it opened, and I was able to quickly leverage some of my menu code from The Walk & Talk to quickly stand up menus, so I was able to focus on gameplay. I used a few asset packs (with some modifications to support the different seasons) and a pleasant song by Joth.

I spent a good amount of time on the wheels themselves, with support for wheels turning within wheels. Wheels controlled the seasons, the day night cycle, monster births and deaths, and the appearance of apples. The unfortunate aspect of it was, of course, that it was hard to focus on the wheel as well as the game, mirroring problems that The Walk & Talk did as well. It was ameliorated in this, since there were visual indicators of all of the cycles in the game screen, but I liked how the cycles looked so I wish more people could have appreciated it.

I also ended up quite happy with how The Appeasement of Cyclus ended up. It did end up being too hard for most people,6 but I’m really happy with the difficulty, despite how challenging it is. There are no unfair deaths, and it rewards you for taking advantage of the cycles. I published this on March 4th, almost 17 hours before the deadline, since I was happy with what I had.

What I Learned

  • The value of having some flexible code that you can use for later projects.
  • If you’re happy with your game, it doesn’t really matter what other people think about it.
  • You can do a whole lot in a few days if you’re motivated.

Beginning to Falter

Boar3D: Becoming a Bore

I started working on a game that I code-named Boar3D (a raycasting game, like Wolf3D, hence the name) on February 17th, shortly after I completed The Walk & Talk. I wanted to gain an appreciation for the technology, so I decided to attempt to create it using Phaser 3 and images to simulate 3D. I wanted to gain an appreciation for the history of FPS game rendering.

I took the opportunity to switch from using javascript to typescript, which adds some type safety to javascript. I worked hard on this, getting walls and doors, as well as entities working. The commits start getting less frequent as the Extra Credits Game Jam gets closer, and I switched gears to work on that. I came back on March 8th, and then again on the 13th, and then I just stopped. I planned to come back to it, but I never did.

Why it Failed

In some ways, this project was doomed7 to fail from the start. I never found Wolf3D all that engaging, and this game was heavy on the art side. This would involve level design (although admittedly, I don’t believe this was that large of an obstacle). Phaser 3 wasn’t exactly the right tool for this, and how I was using it introduced a bunch of overhead.

Additionally, I think I was burned out on making games at the time. I’d been doing it pretty much continuously for two and a half month (which may be a record for me), and I think my brain needed a break.

What I Learned

  • Experience in using Tiled to generate levels (which I have since forgotten, but that’s alright).
  • How to set up and use typescript.
  • How raycasting systems work.

Looking back on this, I’m not that upset that I didn’t complete it. I implemented a raycasting engine, and that was really what I wanted from the experience.

Circle Shapes: Losing Focus

Circle Shapes was the code name for a project where you’d rotate a circle with shape indentations in the center, trying to match shapes falling towards the circle with the shape on the circle itself. I envisioned it as a mix between Super Hexagon and that Undyne fight from Undertale. I worked on it a few days, starting on March 10th and ending March 16th. A keen eye will see that it’s mostly overlapping with the second half of Boar3D, and I think that didn’t do either project any favors, but I was clearly not eager to go back to working on Boar3D.

Why it Failed

Burnout from making games, and trying to do two games at once without formally closing the book on the other.

What I Learned

Nothing, really. There’s a total of nine commits on the repository, and if I want to revisit it, I’d probably want to code it from scratch.

Type It!: A Quick Effort

I started Type It! on January 20th, full of vim and vigor from my work on Four Block Drop. I all but completed it in two days, stopping work on it on January 21st. It was sort of a back pocket game—something I could pull out if I was near the end of the year and I hadn’t finished 12 games. It was inspired by Bop It!, but using the letters on the keyboard instead of some weird chimeric abomination. At the same time I made Tap It!, which was similar but involved phone gestures, like tapping and swiping. These were designed to be sibling games, with both counting together as one game.

That didn’t happen. On February 23rd, I converted the project to typescript (I’ve since done that for all of the javascript versions). I worked on it March 10th-12th.8 I came back again on the 18th-20th, and published it on April 1st after realizing that I wasn’t going to have the drive to work on games for a while. Ironically, this put me the farthest ahead I’d be in the year.

There’s not anything impressive about Type It!, but I still go back to play it from time to time. It’s a fun game!

What I Learned

I’m not sure there’s anything I learned from this project, to be honest. It was the simplest game I had done at the time, and I was always using things I’d learned from other projects—Phaser, typescript—in this one instead of the other way around.

Back in Action

Poetry Without Motion: Salvaging Something

Poetry Without Motion has a long pedigree. When I first played The Beginner’s Guide, the section where you see all the game ideas on the walls sparked something in me. I really wanted to make a procedurally generated café, where you could sit down and drink coffee (think Winter from A Slow Year) and talk with other people in the café. Those people would represent different game ideas I had, and I could have a back and forth conversation about those ideas.

This expanded to wanting to make a whole city block, with cafés, bars with musicians, theaters, and some other concepts all procedurally generated. You’d be able to take a subway between them. If you’ve been reading my weaknesses with previous games, you’ll likely figure out what went wrong here. Well, part of it at least. Yes, this is a very art-driven concept. It also involves procedural generation, which Unity does not take all that kindly to when it comes to lighting or performance.

I never really gain purchase with the café idea, but I did work on a theater. In January 2018 I made a Unity prototype that would recite plays9 and poetry. After working on it for that month, I put it aside (I can’t remember why). On July 7th of 2019 (remember, I should have finished this game by May to be on track), I picked it back up.

I wrote a text box system (that would correctly handle wrapping, tags, and breaking paragraphs into separate text boxes), and hooked it up to a database of open source poems that I had scraped from the web. At the same time, I expanded the randomness of the poetry areas, and added a menu (always a big hurdle for me, before I wrote what would end up being Menutee).

I removed the racist poems I could find from the database (Rudyard Kipling, you know what you did),10 and published it.

I have a soft spot for Poetry Without Motion. It’s among my least played games, with a whopping 9 downloads. I quite enjoy the atmosphere, and even though it is incredibly niche, it’s been a fun way to find some great new poems.

What I Learned

  • Good-looking procedural generation is hard.
  • How to do text boxes properly.
  • A model for menus that I’d carry forward in all of my games.
  • How to create the structure for procedural generation that I’d use in a later game.
  • Some very basic animation code.

Deeper and Deeper: From A to B

Poetry Without Motion had helped me get my groove back. LOWREZJAM 2019 was starting on July 31st and I was ready to get into it. I was in a procgen mood, and wanted to explore creating a dungeon, but without any of the normal combat trappings.

I wanted the areas to be the star of the game. The jam made both made that possible and made it hard, as the game is limited to 64x64 pixels.11 To go with the aesthetic, I also limited myself to only using three colors in each texture. This forced me to make some hard tradeoffs, but in the end I think it has a more unique style because of it.

I generate dungeons by running a series of what I call alterers, one after another. Alterers can do a variety of modifications on the dungeon space, such as stamping a pattern (like generating a maze within a space), connecting all disconnected areas, or placing entities in an area.

This is a fairly powerful concept, and it permitted me to make any tile-based dungeons I could think of.12 Ultimately, I ended up generating a dungeon with 10 distinct floors.

I did run into some issues with generation, such as wanting to paint some walls in a certain terrain with a different texture, but I was able to use a hacky solution13 to work around that. All in all, this was a very smooth game jam experience for me.

It was also my most personal game. It explored some things (admittedly hamhandedly) that I’d been feeling, and I felt more than a bit vulnerable when I saw a coworker playing it. Thankfully, there’s some NPCs that you have to talk to to understand what’s going on, and they attacked them instead. Very few people who played it got what I was going for, which ultimately I’m somewhat happy about.

For this, ultimately a game about going deeper and deeper into a hole that you have no way to get out of, I wanted to have two endings (one where despite everything you get out, and one where you, well, don’t) and I wanted them to be partially based on your actions. If you talk to the goblins, you’re more likely to get the positive ending, and if you attack them, you’re more likely to get the negative one.

Attacking them also causes the goblins to run to the exit (making them go farther down), which means that it’s the fastest way to progress through the game. So if you’re not in the mood to explore, you can lash out at those around you to get deeper, faster.

Anyway, I didn’t want it to be something that you can game entirely. After all, sometimes you can make all the right choices but it doesn’t make a difference. So even if you do everything right or everything wrong, you still have a 25% chance of getting the other ending. Is life way more complicated than that? Of course, but having it be completely random felt too cruel, and, honestly, I was in a great mood when I was making this game.

The biggest complication I had with this game was exporting to WebGL. It takes much longer than a normal build (I believe it was about 10 minutes), and had a few bugs that other versions didn’t. Unfortunately, there was a bug involving falling through the floor that only popped up in WebGL builds that I was not able to fix. It wasn’t gamebreaking since it would just take you to the next level, but it was unfortunate.

I published this on August 17th, around 3 hours before the jam deadline, putting me halfway through my game goal at two thirds of the way through the year. I’m proud of Deeper and Deeper. It’s the most vulnerable I’ve been when making a game, and each environment looks distinct and, if I dare say so, beautiful in its low-resolution way.

What I Learned

  • Dungeon generation is fun!
  • If you want everyone to realize what you’re doing, you have to be even more upfront about it than you’d expect.
  • WebGL is a pain, but probably helps with getting people to play jam games.

Next Time

The next post will cover the second half of the games that I made in 2019, from Out on a Liminal to the mad dash to finish Getting Out before the deadline, while fighting off the zombie of Four Block Drop.


  1. As it happens, this didn’t exactly work out. ↩︎

  2. I realized after I finished it that it bears a striking similarity to the missions in Assassin’s Creed where you’re tailing a person, although I despised those missions and enjoyed my own. I might be biased though. ↩︎

  3. I liked its simplicity, but it wasn’t well-received. ↩︎

  4. I don’t advertise and don’t particularly care if people play my games. ↩︎

  5. Technically it wasn’t shovelware, but it seemed like there was some template people were using to push them out. I want to say that they were flash, but I don’t know if the timeline lines up. I have no memory of the names of any of these, and I wouldn’t be surprised if they had disappeared from the Internet. If you think you know of an example, send me a link because I’d love to drop it in here. ↩︎

  6. In fact, I only beat it after uploading the game, something that should have been a red flag. And that was the normal mode. The hard mode was the same challenge, playing at 1.25x speed. ↩︎

  7. Pun intended. ↩︎

  8. Really splitting my efforts here. I’d forgotten that I had three plates spinning simultaneously, not a great idea. On a side note, I currently have four plates spinning as I write this (and that’s not counting this blog post). Oops. Let no one say I learn from my mistakes. ↩︎

  9. They had to be in xml format, so it had a limited repertoire: a test play by me, The Comedy of Errors, and The Witch of Coos. ↩︎

  10. I’m certainly not the right person to make this call. There’s a lot of low-hanging fruit for removal, but there’s also a good deal of poetry from the Harlem Renaissance that have frowned-upon terminology now that I left in because that was historically appropriate at the time. And because if you’re looking for poetry in English that isn’t just from white men, you have limited options. ↩︎

  11. Scaling the game up is permitted. ↩︎

  12. And do art for: a more limiting factor. ↩︎

  13. In addition to a terrain and tile type, each tile can have a paint style, which causes it to be drawn differently. ↩︎