Monday, February 3, 2020

Global Game Jam 2020: Disarmed

I hosted Global Game Jam 2020 last weekend at Ball State University, with generous cosponsorship and co-organization from the STEM Living Learning Community, Office of Housing and Residence Life. The theme, as announced in the keynote address, was Repair. I thought this was a good theme, being broad in interpretation yet clearly constrained.

My oldest son came with me again, and like last year, we planned on working together on a project. We have been enjoying Brief Battles and Towerfall recently, and so we talked before the event about trying to create some kind of local multiplayer competitive arena game. After hearing the theme (and taking care of a bit of site administration), we hit the whiteboards and started sketching ideas. My son pitched the idea that you were robots trying to repair yourselves, and you could use the things you pick up as weapons against the other robots. That became the core gameplay, and the rest emerged from there.

We called the result Disarmed. Here are the title and gameplay stills from our Global Game Jam project page:

The players click in from their controllers, and the game runs with a 60-second timer. You start with no arms, but you can jump to a nearby platform to grab a harpoon gun arm. That gives you three shots with which you can try to hit the other robots: a successful hit on an armed robot knocks its arm off, and a successful hit on a disarmed robot counts as a kill. After the 60 seconds are up, you get a report about how many deaths and kills you accumulated.

My son and I were using found audio, but right across the table from us was a composer working with just one other person on a project. On Saturday, I showed him what we were working on and invited him to create an original soundtrack, if he felt so inspired. His name is Nathan Cobel, and it turns out he's a professional musician and tutor. He ended up creating two pieces for the game: a short loop for the title screen and a longer one for in-game—pieces much nicer than the placeholders we had tossed in from browsing the Web.

We used Unreal Engine 4.24 to make Disarmed. My son ended up drawing all of the art using Piskel, which I had only shown him once before, many weeks ago. He quickly came to like it and became able to export sprite sheets and bring them into the engine. The only place where I really got my hands dirty in the artwork was in making a simple custom material to tint the single grey robot into the four different player colors. It may be worth mentioning that my son has made his own pixel art using Construct 2 in the past, and he's played a little bit of Dead Cells, but I'm sure he's never really studied pixel art. I don't know a whole lot about it myself, and in fact, I'm not really a fan of the genre. There were a few cases where I asked him to redraw some things to improve the contrast, and I think the final result is pretty good for a pair of guys who were winging it on the visuals.

In the project page, I checked the two diversifiers that matched this game. One is "!Coding", which is defined as " Don't write a single line of text to create your game. Only use game engine built-in features and visual scripting." I checked it even though I don't agree with it, since we technically followed it. However, it repeats a dangerous idea that visual scripting is somehow not coding. UE4 Blueprint is as much programming as any other programming language. Making a video about this is on my list for the semester. The other diversifier I selected was Protip, which is defined as "All members of your game jam team get 8 hours of sleep, 10 minutes of exercise and eats a meal that includes vegetables each day of the game jam event. Upload a brief development diary along with your game upload to document these actions." I checked that even though we technically didn't get it. First, we didn't upload a development diary, although maybe this description counts. Second, I know from talking to my son that neither of us slept eight hours the first night of the jam despite spending eight hours in our beds. If I had known that he also was not sleeping, we could have done some middle-of-the-night development! Since we live a ten-minute walk from campus, it was easy to get the exercise, and we do always make sure to eat our veggies.

I want to share a few technical notes about the game, in part so that others can understand how it works, and in part so that I can come back here and remember how it works :)

Local Multiplayer in UE4. In order to allow a player to "click in" to join the game, they have to already have a PlayerController created. There's always one player controller (number 0), and so the title screen game mode creates three extra controller objects. These controllers listen for the player to click in, and then tell the game instance to increment the number of players. This worked except that then when going into the main game mode, we always got four robots in the level because there were four player starts. Our solution was, just before leaving the title game mode, to remove some of the player controllers. This did the job, although we realized in testing that it's a bit sloppy. We should have kept track of which controller ID was clicked in, because our current approach is prone to a problem if there are more controllers plugged in than actual players: someone might "click in" on controller #4, then the game starts, and it removes controller #4, leaving that player high and dry. Aside from some of this management, local multiplayer was really a breeze to set up.

Physics vs Projectile Movement Component. The harpoons were launched by enabling physics on them and adding an impulse. This seemed to work fine when testing in editor, but when we launched the game from a built executable, we saw weird things happen: the harpoons would often get stuck in the robot who was firing them, despite the fact that our collision handling should not have let this happen. It wasn't until just before the end of the jam that I realized I could try to work around the problem by switching from physics to projectile movement component. This solved the problem, although I'm still unsure as to why we would see different behavior in PIE vs in the packaged game. The rule of thumb that I forgot was not to mix and match physics and non-physics ideas into the game.

Spreading sprites across an area. This is a pretty minor point, but it struck me as interesting. I have an object that is responsible for spawning one sprite onto the screen for each player, such as at the end of the game to show the scores. There's a horizontal range over which I want to spread the objects, and so I started trying to determine the X positions of each sprite algebraically. It dawned on me that this is really mapping from one range (player number, which goes from 0-3) to another range (X coordinates, in this case -300 to +300 from the position of the spawner). This can readily be done with the Map Range node. Here's an example from BP_RobotSelectionSpawner:
Like I said, it might be kind of obvious, but when you've been jamming for 40 hours already and your brain is a bit addled, it feels good to remember that if you think about a problem declaratively, you can solve it more elegantly than with ugly math nodes.

You can download Disarmed from the project page, although it will require 2-4 controllers and Windows to be playable.

I don't think I'll have the time to write up any more thoughts about the Jam, but I will say that we had the best turnout at our site in four years. There was a lot of energy in the room. I think that offering catered lunch on Saturday was a big influence in having people come back and work. I was very pleased to see the first analog game created at our site, too; it's something I've encouraged for years, but this is the first time one was finished.

Thanks for reading! If you have a chance to try Disarmed, let us know what you think. The folks who played it at the Jam seemed to really enjoy it.

No comments:

Post a Comment