Global Game Jam 2020

Build a game in 48 hours

Last weekend (Jan 28), nearly sixty people descended on DePaul’s CDM to take part in the 2020 edition of the Global Game Jam. As I’ve been getting more and more involved in the video game development community, and my computer programming skills have improved to the level of barely competent thanks to time spent messing around with Unity, I decided that I would dive in for forty-eight hours of video game development madness.

The results?

Tux Repair: Dungeon Cleanup

Our game wasn’t quite what we scoped and it has plenty of bugs and weird behaviors I still can’t figure out—but I couldn’t be more proud of it. I would absolutely do another game jam soon (though I’m not sure I’m ready to commit to Train Jam…).

You can play our game here, and you can check out all the amazing games developed at DePaul at the Global Game Jam website.

What is a (Global) Game Jam anyway?

First, some context. A game jam is a video game version of a hackathon or 24-/48-/72-hour film/design/create challenge. Teams get a short window to create a video game “from scratch”, based on a prompt or challenge. At the end of the challenge, everyone demos their games, and gets to see what everyone else put together. There are sometimes prizes; for the DePaul Global Game Jam (GGJ) the winning team received a tour of Iron Galaxy Studios, current home of Killer Instinct, Extinction, and several popular system ports.

The Global Game Jam is a global game jam. Started by Susan Gold in 2008, the GGJ has grown to 113 countries and develops over 9,000 games annually. That includes all of the official statistics; I quickly learned from some of the folks there that it is common for developers to skip the official jam but take the chance to leverage an artificial deadline to get the creative juices flowing.

Teams usually assemble on the day of the event, though, it being held at DePaul, there were several pre-formed teams consisting of current CDM students. The rest of us found each other that day. Before assembling, Susan Gold (who is also a DePaul faculty member as well as a game jam founder) gave a talk to the assembled jammers. Her talk was followed by the kickoff video/keynote, and then we were off to the races.

Susan Gold speaking at GGJ 2020
Susan Gold speaking at GGJ 2020 (Photo: Ross Hersemann, IGDA)

I was on a team of four, which was either the smallest or second-smallest team at DePaul. Our group consisted of:

  • Ryan Sizemore, 3D artist/designer,
  • Rob Goetz, lead programmer,
  • Andres Chamat, musician and sound designer,
  • Me, jack-of-all-trades and rookie programmer
The assembled team

We got the prompt: “Repair,” and sorted out some logistics. And then it was time to make a game!

Late nights are fun, right?

We spent a good twenty minutes trying to find an unlocked room somewhere in the CDM where we could huddle and come up with something. While hunting, we began batting around ideas having to do with “repair.” Reassembling sci-fi dystopias, repairing broken relationships, fixing robots—all these and more were discussed. But ultimately it was Ryan’s pitch of a dungeon cleanup crew that won us over. It was a simple enough idea to execute, the scope could be managed more or less on the fly, and we could build a 2D pixel art game à la The Legend of Zelda that would also be a crowd pleaser. Two of us had also played Viscera Cleanup Detail, and I think the irreverence of the concept also appealed to everyone.

We ironed out a few more details:

  • Protagonist: Nigel the Penguin. There was a claymation penguin in the GGJ intro video, so we went with it.
  • Obstacles: Dungeon enemies, traps, and the adventurers hell bent on making messes for you to clean up. Crucially, the job was to be made harder by the fact that you were not immune from the perils of the dungeon, meaning that repairs had to be done strategically to avoid trapping yourself.
  • Engine: Phaser. Rob recommended it, as he is primarily a JavaScript developer and web dev has really short iteration cycles. No need to wait for a compiler—just refresh the page. I have some limited JS experience thanks to my last job, so there was the added benefit of my being able to actually provide some programming support.
  • Infrastructure: I set up a GitHub repo and a Google Drive folder for us to pass around assets, and wrote a game design document (my main contribution).

And divided up responsibilities:

  • Andres would write all the music, and figure out sound effects for smashing vases, rebuilding skeletons, opening doors, etc.
  • Ryan was in charge of all the art, a challenge complicated by the team's decision to go with 2D pixel art, a novel medium for him.
  • Rob would write the game code, and take advantage of Tiled to quickly iterate on level design.
  • Grahame would do the UI development.

And then we were off. Andres and Ryan began cranking out the game assets, while Rob and I began building the game.

On the asset side of the house, Ryan and Andres knocked it out of the park. Andres, who worked from his home studio for most of the jam, put together a series of classic dungeon themes, perfect for the tense crawl/campy eighties game vibe we were going for. Ryan mixed and matched publicly available assets with his own creations; the look and feel of the game is all due to him:

Screenshot from Tux Repair

On the programming side of things, it’s safe to say Rob carried the team. Using a combination of JavaScript chops and Google-fu, Rob figured out how to directly load maps built in Tiled, create events and behaviors for the various game entities, and even get the sound effects and some of the animations working. He had to pull an all-nighter on Saturday, but doing so made it so we had a game to turn in and present.

I was less productive than I’d hoped to be. After dealing with the infrastructure and project setup, the best way for me to contribute was through programming. So I dove in, writing a UI manager class and status bar for the game to show the key bits of info to the player:

  • Health, consisting of three Zelda-style heart sprites
  • Time to the Next Hero, telling the player how long they had until a new adventurer would enter the dungeon and start breaking things again
  • Coins, the amount of wealth the player had pocketed while resetting things
  • Bones, the number of skeleton parts the player had with which they could rebuild the dungeon's monsters

Writing the logic for each part of the UI was pretty easy and it took me maybe an hour to get it all sorted out. My issues came up when I tried to connect it to the actual game.

Issue #1: Node.js ≠ JavaScript

In retrospect, this goes without saying. Node.js is a JavaScript framework that messes around with how the language does certain things. So all Node is JavaScript, but not all JavaScript is Node. However, I was inexperienced enough at coding not to know that the work I’d done on a Node web app was not directly analogous to general JavaScript development.

I’ve been teaching myself Unity, and the way it passed around classes and properties is very similar to the way the Node web app I’d worked on had passed things around. It is much easier to take advantage of encapsulation when using Node and other ES6 JS frameworks, and I had not realized how core object-oriented programming was to how I had been learning to program.

Classic JavaScript is more of a functional language, which I still have trouble with as a paradigm. It shies away from mutable states and data, which was how I’d written things for the UI. When I went to connect them with the Phaser engine, I got errors ranging from basic import issues to all sorts of crazy complicated stack issues I still don’t really understand.

Finally, though, I got my UI connected to the game, and was successfully using console.log() to display UI changes. I also learned a bit about a new (to me) programming paradigm.

Issue #2: Callbacks

I needed to write a timer that restarted every time a new hero appeared in the dungeon. While the timer was actually a game element and not a UI element, I needed it in place if I was going to ship a working UI. Since Rob was occupied making the game actually work, I took a crack at it.

Quick game development lesson: all game engines have an update() function, which contains a set of instructions the game runs prior to drawing a new frame on screen. So in pseudo code, every time your screen refreshes, your game engine is doing something like:

// example pseudocode...
function update() {
    getPlayerInfo();
    getEnemyInfo();
    calculatePhysics();
    updateUI();
    // ...

    render(); 
}

So you need a timer that counts down and then triggers something (e.g., a timer reset) every X number of seconds. How would you do it?

The obvious solution is to simply increment a counter every frame, and when it hits X seconds, do the thing:

// assuming 60fps
int frameCount;

function update() {
    frameCount++;
    checkTimer();
}

function checkTimer() {
    if (frameCount >= 600) // 60fps * 10 sec = 600 frames
        // DO THE THING
}

There’s an issue here, though: not everyone’s monitor refreshes at 60fps. Some people refresh faster (gamers often have 144Hz monitors); folks on crappy PCs will refresh slower. A person’s hardware should not directly affect how the game runs.

So we need a timer. And to write a timer in Phaser, you need to use callbacks.

Problem: I had no idea what a callback was.

Solution: I forced myself to learn about them while super sleep deprived.

A callback, I now know, is just a function passed to another function as an argument. The first function runs the second function as part of its routine. Which is perfect, because we can set rules on if/when the second function executes.

And, as it turned out, Phaser has built-in support for managing game time. So creating a timer was as simple as launching the level with a function that would callback a function every second:

function create() {
    // ...

    var timedEvent = this.time.addEvent({
      delay: 1000, // delay each event 1000 ms (1 second)
      callback: onEvent, // run onEvent() when executing callback
      callbackScope: this,
      loop: true // repeat forever
    });
}

function onEvent() {
  timer -= 1; // subtract 1 from timer
  UI.time = timer; // update UI
  if (timer <= 0) {
    world.newHero(); // create new adventurer
    timer = world.heroTime; // reset timer
  }
}

And that was it. Callbacks!

In terms of return, callbacks have got to be one of the most useful tools I picked up at the GGJ. I’ve since implemented callbacks in a number of places in my personal video game project, and they solved a lot of issues I was trying to resolve.

Issue #3: How do you actually show the UI?

The next thing to do was to actually show the UI. How to do so was not readily apparent to me. I floundered around for a little bit in the Phaser documentation and on various forums before I discovered that Phaser allows you to overlay a <div> element and edit it using the DOM manipulation techniques jQuery provides. It took me a little bit before I got the DOM tools set up and figured out how to anchor element coordinates… but then there was hope! I had a box in which I could put my UI.

There was just one problem. I don’t actually know how to use jQuery.

Upon realizing this fact, a good 2-3 hours of despair set in. It was also right around the time Rob had hit a wall on getting the doors to work properly, and it seemed, with less than sixteen hours to go, we were not going to have a finished game.

I poured over the Phaser docs, forum posts, StackOverflow, looking for something to spark understanding or an answer. But then, finally, after fourteen hours of solid coding, I had that little switch flip, and I understood how to show and edit text and sprites.

I got the bar working, and showing, and finally relaxed… only to panic when it disappeared and no one could bring it back. It was a puzzle we did not solve in time, forcing Rob to use an older UI build where some of the sprite textures were broken in order for us to have a working game.

The issue? I had zoomed the camera in to improve the feel of the game… which zoomed it in past the UI.

Wrapping Up

We submitted our game on Sunday. Ryan whipped up a banner and a name for our project, Tux Repair: Dungeon Cleanup, and demoed it to the rest of the DePaul jammers. The demo went well (minus some broken UI sprites), and since we were first we got it out of the way quickly, so we got to relax and watch the other games come in. They were all extremely creative and there were some unique takes on the “Repair” theme. Games ranged from restocking Costco to a cowboy duel on the moon.

The winner at DePaul was Tomar the Love Angel, a Metroidvania where you play an angel trying to repair a broken heart (from the inside). You can download the game (and all the other games) from the DePaul GGJ Games Page. And you can play a slightly modified version of our game at grahamewatt.com/tux-repair

Enjoy!

« Previous
Next »

Grahame Watt

contact@grahamewatt.com