Ctrl+Out dev commentary

Warning: This page contains spoilers for my game Ctrl+Out; I recommend you play that game first.


This game was made for the GMTK Game Jam 2020, which had the theme "out of control". Games in this jam would be judged on three categories: originality, presentation, and fun. And one other constraint: the "vast majority" of code had to be written during the jam.

That latter constraint ended up constraining the design somewhat. None of my game jam games so far have used any sort of pre-existing third-party framework (e.g. I don't use Unity or anything), which means a lot of things that might otherwise be handled by a framework, like making sure the framerate and scaling are right and handling input, are things I've done myself. To make things easier on myself, I've been taking various bits of non-game-specific code and putting them in a separate file that I copy to all my other games (sort of like my own framework). The problem: for most of my games, the non-game-specific file is larger than the game-specific code. If I just used it as-is, then it would most likely not be the case that the vast majority of code would be written during the jam.

My solution to this problem was to only use a small part of that file, and then delete the parts I wasn't using. I looked through the file and determined that the largest things in the file were keyboard-handling code (which includes support for remapping the keyboard and simulating a controller on a touch screen) and code to display menus, so I decided that I would try to make a game exclusively controlled by mouse/touch (so I could get rid of the keyboard code) and not have an options menu. (This ended up sort of working with the theme: lack of options menu means less control than usual for my games, and my intro about my keyboard-handling code not working ended up being more self-referential than it otherwise would.)


A few ideas that I came up with between when I heard the theme and when I started actually doing the programming:

I chose the last of these options, as this was something that I hadn't seen done before at all. (Looking back I might have been a bit too focused on the "originality" criterion, trying to make something that hadn't been done at all, at the expense of other things.)

Then I tried to come up with what sort of game I'd make. I decided to try to make something like a roguelike, at least in terms of having a procedurally-generated map; for one thing, the idea of taking something out of the designer's control was mentioned in the theme reveal video, and using procedural generation does that; for another thing, if the map isn't predetermined, then I can make the next room that the player hasn't been in be the exact type of room I want them to have. (This means that I don't actually generate the map ahead of time; I generate each room as the player comes to it… mostly. More on this later.)

And then the actual mechanics themselves:

The bug

A few hours after the deadline, I replayed the game and ran into a bug: when I tried to go down one of the paths, I got an error, which I hadn't gotten when testing the game before the deadline. Later that day, someone was streaming a bunch of games from the jam, and they streamed my game, and encountered a similar error on two attempts of playing my game.

The problem is with the room generation. Like I mentioned earlier, most of the time, the game generates a room when you actually get to it, specifically the moment you enter the path to the room (which is when the error happens). However, to ensure that the player doesn't get stuck in a dead-end, it'll sometimes generate other rooms as well, and the code that was supposed to do that sometimes tried to generate a room that was already generated. This sometimes violated the assumption that there's a next room to go to that hasn't already been generated, so the game would try to generate a path in a nonexistent direction and crash.

After discovering the bug, I uploaded a simple fix to my website and put a notice in the description. However, the 1.3 version (after the final results were revealed) just removes this extra room generation entirely, because it wasn't necessary with how I ended up doing things in the final version (when I wrote that code, I had a more complicated idea in mind for how I'd handle room generation). A side effect of this is that level 3 used to sometimes have split paths with short dead ends, but now no longer does.

(Also, it turns out I introduced another minor bug with the fix by changing the version number. In particular, the version number overflowed the window in the ending screen, because "post-jam version" is longer than "jam version".)

Things I might have done differently

Looking back (and realizing how many entries each person was probably judging), I think I probably should have made something where it was easier to see what I was going for close to the start of the game, rather than intentionally obscuring it and requiring two or three playthroughs to see that something strange was going on. (…so maybe I should have done one of my other ideas.) I still don't know how many people who rated or commented on my entry actually know about the illusion-of-choice thing; maybe some of them just thought that the control-key thing in the intro was my main use of the theme.

Also the unskippable intro was a bad decision. It was supposed to fit with the theme by giving the player less control, but it ended up just taking too much time, especially when I wanted people to play multiple times. Version 1.3 fixes this (click to skip the intro).

Some other things:



Some more spoilery details about what I changed in version 1.3 (after the judging period was over), in addition to what I mentioned in the version history page:

(Also, just to be clear: version 1.2.1 was before the deadline for the jam; 1.2.2 was the bugfix version after the deadline during the judging, with a link in the description; 1.3 was the first major update after the judging finished. 1.0-1.2 were other versions that I uploaded before the deadline so that I'd have something in case I didn't get the final version done in time.)


Encounters are now numbered and you only see enemies when you're supposed to interact with them. I hope this cuts down on potential frustration caused by evading enemies and also makes it a bit clearer what's going on (especially since the end screen now shows the results of each encounter).

Also now buying keys is no longer an action that has to occur in sequence. And neither is getting mind-controlled.

Other notes

The music and sound effects (other than the typing at the beginning) are all triangle waves, which are used in chiptunes...