Bullet Hell with no Toilets: A Retrospective on Precision Jam 2019

Every game I’ve ever worked on and had something good to show for it in the end has followed this process, and I had a few more things going for me when I signed up to make No Bullets in Hell for Precision Jam, Feb. 15-22nd, 2019: I had several things in place—from source control on Github and automated builds with Unity Cloud Builds to a recovery USB stick and a backup copy of my development folders on a second hard drive—to avoid a lot of common disasters that occur in software development, especially on small indie teams; I had a collaborator who is a talented artist and a good communicator, and I got a good night’s sleep every night during the jam. What follows is a rundown, in broad strokes, of how Josh Squires and I put this game together, and the various challenges we faced.

When I heard that Nina Freeman’s Discord community was holding another game jam, I knew I wanted to make another game in Unreal Engine 4 after all the attention Press E to Forget got. I had been working my way through these Udemy classes since then, and I wanted to make something more substantive than glow-in-the-dark vomit (as cool as that is). I posted a message in the gamedev channel on Nina’s Discord with a link to my portfolio site, and the next day I got this DM from Josh Squires, who co-organized the jam and is a moderator on Nina’s server.

Much as I wanted to get better at UE4, I thought over Squires’ message and decided “Eh, I have enough Unity experience that I could probably set up pages for whatever comes out of this jam and my other projects on Unity Connect. Then I could start making a case for myself for freelance/contract jobs if there really are people advertising for help on that site (I’ve heard mixed things about it).”

Before I get into the play by play of the jam, Bill had some questions I want to handle first:

  • How many hours do you think you worked on the game? I can only give a ballpark estimate, but when I look at the times on the commits to the Github repo (that’s changes to the code for you non-techies reading this), it adds up to about 53 hours. I’m sure I got distracted by Twitter or Youtube in that time, and that doesn’t count time recovering from the software failure I’ll describe later. If we count Windows recovery time, it was probably more like 60 hours.
  • How many hours sleep did you get in that week? 8-10 hours per night. I don’t remember crunching or being up at odd (for me) hours. It probably helped a lot that Squires and I are both night owls, and we were in the same time zone at the time of the jam.
  • Bill asked for a play by play on every meal during the jam. I don’t remember everything I ate, and I will not bow down to any corporate sponsor, but my diet was something like this:

via GIPHY

When I got up, 2 White Castle Cheese Sliders with either ketchup and mustard or Sweet Baby Ray’s Honey Chipotle Barbecue Sauce, and maybe a bowl of Nacho Cheese Doritos later on.

The Breakfast of L33T H4X0R5 Everywhere!!!

Then I had a normal person meal around dinner time. This could be spaghetti and meatballs, stir fried hamburger meat with vegetables, soup, etc. and finally some midnight snacks, almost none of them sugary except for dates. Most important of all, I drank 5-6 cups of coffee throughout the day. Running at a buzz of about 1-1.2 Balzacs is good game development practice.

This is a good place to add that I had a chore around the house that would not just get me away from the computer screen, but provide a good amount of exercise as well. Late last year, I wasn’t able to move this pile of wood out of the path of the snow.

I managed to cover some of it with metal sheeting before the snow hit, and I have steadily shoveled away at this makeshift igloo for about a month. Dislodging chunks of snow, launching them over or onto the snowbank in my front yard, kicking logs loose and hauling them to the wood stove upstairs made for a nice workout when I needed a break from the C# scripts.

Ok, back to the rundown. Before the jam started, I helped Squires set up and figure out Github Desktop for source control. This Brackeys video on using Github with Unity and why it’s important came in handy. Then I looked into Unity Cloud Builds and how to connect it to a Github repository. Unity Cloud Builds monitors your source code, checks for changes, and builds the executable program from that code any time it sees a change. It supports almost every platform except for consoles. I wanted to do this after this flub at the Epic MegaJam last year, and while Unity is different technology that, in my experience, is hard to break in a way that won’t show up in the editor, I didn’t want to take any chances this time around.

Once Nina announced the theme, Squires (who had the original idea for the game) and I had a quick, gameplay-focused discussion over Discord that led to a Google Doc with these bullet points:

Future game jammers take note: You’re on the right track if you can nail down a short list of bullet points describing the core gameplay at the start. With this basic idea of the game we wanted to make, we put together a prototype,

and we kept track of each small milestone of the development not just with commits, but with the issue tracker system in Github:

While I’m talking about Github, I’d like to go over the conventions Squires and I had for our source control usage, which are based largely on this article.

As stated in the article, we did use branches, however it was just more convenient to reuse our branches rather than deleting them after merging into the master branch. In a longer term situation or one where we had to be very specific about the purpose of a branch, this would not have happened.

We were careful to make sure who was working on which scene when, but I think we avoided scene conflicts because of our scene convention. Suppose Squires wanted to change the position of the jagged walls in the game. He would open the scene, which would be called “SquiresTesting3” or something similar, make his changes, save, commit, push to Github in his branch, and merge the changes into the master branch. I would pull the changes in SquiresTesting3 into my branch, and if I had to make scene changes, I would make a duplicate of SquiresTesting3, rename it “ArjunaTesting4” (or whatever the next number in the sequence was), make changes, and this process would work back across to Squires’ branch. By the time we submitted the game for the jam, this is what our scenes folder looked like:

If I were working on a project with a lot of different and large scene files, I would not have done this, and I would have looked at Unity’s built-in UnityYAMLMerge tool, but that has its drawbacks too. Prefab conflicts were avoided because there was a clear distinction between items that Squires worked on (UI, walls near the end of the jam, etc.) and things that I worked on (empty objects with scripts components attached, randomly generated blocks, the player character, etc.)

Once we had something playable, we discussed the look of the game:

Then he started on the player sprite:

By Feb. 18th, we broke down what we wanted to make for the game into To-Dos, things that had to be in the game by the time we submitted it for the jam, and Extras:

TO-DO

  • Start Screen
  • Block spawn time adjustment
  • Start block fall-off
  • Add “hurt block” (lava or spikes)
  • Block speedup
  • Play-test/balancing
  • Art stuffs
    • Finalize characters
      • Jump frames
      • Walk Frames
      • Wall-stick Frame
      • Death Frames
    • Basic blocks
    • Hurt blocks
    • Side wall lava
    • Starting block
    • Background
    • Logo
    • UI (Font, Game Over, Start, Side Panels)
  • Sound
    • Ambient/Music?
    • Death
    • Jump
    • Land
  • Extras (nice, but not necessary)
    • 2 Player
    • Lava balls
    • Blocks that shoot lava balls from sides
    • Animations
    • Powerups
      • Double jump?  Multi jump?
      • Invincibility?
      • Score+
    • Art Stuff
      • Character Idle Frames
      • Particles
      • Lava balls

For the next three days, things were running smoothly as Squires and I regularly talked about the gameplay, changes to the design, and any work on scene files or prefabs that could cause a merge conflict. He worked on pixel art, scoring, and UI stuff, while I focused on code, physics, fixing bugs and jank in the player movement, tweaking block spawning and block scale, and picking out sound effects and music. I would also incorporate some of the pixel art as Squires sent it to me and/or imported it into the project. I got the sound effects and music from freemusicarchive.org and the Universal Sound FX Unity Asset pack. Our discussion of which clips to use went like this:

The choice of negative sound clip is even better, I think, listening to all the sounds and music working together in the game. Any more non-chiptune-esque noises would have probably undermined the retro aesthetic.

Then February 21st rolled along, Satya Nadella farted in my general direction, and my computer would not stop getting BSoDs! I still have no idea what went wrong, because I’d get a different fatal error every time it crashed, and I ‘d get a BSoD even when booting into Safe Mode with Command Prompt. Fortunately, I made a recovery USB a week or two before the jam, and I had enough important files backed up or in the cloud on source control that I “only” lost 7-9 hours of productivity, mostly due to my slow internet connection.

After we submitted the game for the jam, Tyler asked about gamepad support. I had all of Saturday and most of Sunday to make changes to the game before Nina streamed it on 2/24, and I had added controller support to Unity projects in the past, so I quickly coded in support for the PS4 gamepad (Tyler has a PS4, so that was the obvious choice). Let’s go for a little walk through the part of the code that lets the player move down by moving the left joystick down:

float moveVertical = Input.GetAxis(“Vertical”);

This reads a value between -1 and 1 from the keyboard if the player is using a keyboard, and from the left joystick if the player is using a controller. The value will be 1 if the player is holding the up arrow/pushing the joystick straight up, and -1 for down.

movedVector = Vector2.down * (downJumpVelocity / 10.0f) * moveVertical;

This calculates a vector in 2D space to apply to the RigidBody2D component on the player character. If you follow the math (and yes, there are other problems with this as well), you can see that the y component of the vector could be positive, enabling the player to move up by pressing up, which is something we never intended. When Saam set what I believe was a new world record for No Bullets in Hell:

I thought he was exaggerating when he said he never used the space bar. Then Squires sent me this minutes before Nina’s stream:

And she played it in a way we never thought of designing for. In the end, we decided to keep it:

Now, almost at the end of this blog post, are we gonna continue development of No Bullets in Hell, add in all those nice extras, and more? Maybe. I’m writing this the week after the jam, spending it catching up on things like recording for the PointlessCast that I set aside for the jam. Find out on the next episode of WAYNE’S WORLD! WAYNE’S WORLD! PARTY TIME! EXCELLENT! widdily widdily widdily widdily widdily

Finally, if you’re thinking about participating in a game jam and you get nothing else from this blog post, remember this:

  • Have source control and automated builds!
  • Focus on small, small subset of gameplay that you can quickly bang out a prototype of and get a feel for that is still large enough to have some little spark of fun playing.
  • Whatever you’re making, having collaborators who are good at their specialty and are good communicators will make a huge difference for your project.
  • Eat better than I did. Consider cooking several meals before the jam and throwing them in the freezer if you can. Make sure that you have something to do that takes you away from the computer once a day and gives you some exercise.
  • The best debugger is a good night’s sleep.
  • Plan for hardware and software failures. Do you have a recovery USB for your OS? Do you have backups? No? Go do it! Go! The blog post is over! Go!

SuperArjunaButt

Permaculture designer and game developer. Biggest toilet fan on the internet.