Sunday, April 26, 2020

Fam Jam #2: Rocket and UFO Game

After the March Fam Jam, the boys were clamoring to do it again. "We should do one a month," they shout, because shout is the default volume level with four boys in the house. I love their enthusiasm and that the joy they get from the experience overrides both the essential and the accidental frustrations.

TL;DR: We had fun making a game, and you can play it online right now (as long as you have a keyboard). Here's a gameplay video for those who cannot play it directly:


The night before the jam, I did a little bit of prep work. I knew we would end up using Godot Engine since that's what #1 Son has been spending a lot of time with. I set up a repository on GitHub, copying over some of the structure and utilities from Canning Heroes Special Edition. I completed that project since the last Fam Jam, and in so doing, learned more about best practices for Godot Engine projects and how to script builds and deployments. Whereas Joe Johnson Gets Captured used the repository docs folder to publish on GitHub Pages, and hence had the problem that pushing and deploying to master were the same process, Rocket and UFO Game takes a more elegant approach of using the gh-pages branch.

Around 7:30 in the morning, with my morning cup of tea, we set a deadline of 8PM to finish the jam. We formally assigned #3 Son to be the Creative Director. He had been asking for days—maybe weeks—if he would be in charge next. I cautioned him that we had to have modest scope, as we only had one day. He asked if we could extend the deadline—this kid has already learned something about estimation! I reminded him that we had just set the 8PM deadline, and #1 Son commented that the deadline is a crucial part of the jam process; he has done a few jams now and clearly has gotten his head into what it's all about.

Our Creative Director paused as he tried to simplify his design ideas, and then he said he wanted a game in which you control a rocket that is always moving forward, with a force field, who shoots UFOs that drop chickens. Makes sense to me! I expected his design to include more technical details of rocketry, since this is the kid who devours any information about NASA, the Apollo missions, rockets, and so on. He's currently saving up his allowance money to buy a fancy Saturn V model kit. I am glad he chose something a bit more modest and conventional.

I dug into some of the rocket controls while my wife and #1 Son made some delicious sourdough pancakes for breakfast. They used sourdough starter that is literally older than I am, gifted to us from a family friend. In my first pass, I kept track of velocities and changed the position of the rocket on each tick, but then something I read reminded of the built-in move_and_X methods. Using move_and_collide instead clearly was the best option, and so that's how I approached the rest of the pieces.

After breakfast, we made a more formal plan of who was working on what, and the day proceeded with excitement and creativity. Here are a few vignettes:

I wanted an infinite scrolling field, but we could not sort out how to make that work, and so we ended up just bounding space. I would like to investigate how a background could be infinitely scrolled under a camera, since it seems to me it must be possible.

#2 Son had a blast using bfxr to make the sound effects. He also made a song for the game in LMMS, but when we put it in, the intensity of the music crowded out the sound effects, and it was hard to tell what was going on. We moved that song to the title screen instead.

I wrote a short loop for the main gameplay, with the idea that I'd hand it over to #2 Son to add some leads, but clearly we were having a mismatch. I think I assumed he had a bit more savvy around how music and songs were structured than he does, so I just took this over. Ironically, then, my first song was terrible. It was in Dm, and that was just wrong for a game with space chickens. I threw that away and did a similarly-voiced song in E major. The B part of the song was, again, terrible, so in the interest of time, I tossed it, and we're left with a 12-bar loop that is similar in tone and repetitiousness as Goofball's.

It may seem like a small thing, but I think the flames that come from the rocket are wonderful. #2 Son took a stop-motion animation class with BSU animation professor Brad Condie last Fall, and one of the most interesting things I saw him do was make a crackling campfire. I had never really thought about anything like that before: he insisted it was relatively easy, but like so many things, it's all about knowing the tools of the trade. I encouraged him to work with #4 son to collaboratively draw a few frames of flame animation for the rocket. We got those scanned and put into the game, and I think they are great.

I disagreement with my wife in the morning which made me reflect on how she was too peripheral to the process, so I did what any loving husband would do: I taught her to use git. We set her up with ssh keys and a GitHub account and downloaded Godot Engine onto her machine. I gave her a primer on how to interact with the version control system, and in no time, she was able to not just make content, but integrate and test it herself. Once she got her sea legs, I explained to her that in my multidisciplinary game studio classes, my rockstar artists will make sense of version control, which empowers them to be first-rate creative contributors to the project, whereas my timid members will avoid learning about version control and, as a result, only ever be on the periphery of the project.

Incidentally, I (re-)learned two important facts about git during this process:

  • Using git pull --rebase will avoid those annoying merge commits.
  • git clean -n and git clean -f will clean out junk such as post-merge detritus from a repository.
Later in the day, my wife wanted to approach the title screens by designing them in Inkscape and then exporting them as images, as she had done in the March FamJam. I explained how parts like the instructions should really be done in-engine so that we can change the text easily, and how even the logo of the game, if it is only plain text, could also be done in-engine. Both of these reduce iteration time, which happened to be the concept that sparked our little disagreement in the morning. She had already become proficient with git and could run the game herself, so I gave her a quick tutorial on how to design a UI within Godot Engine. She has a lot of experience and talent with desktop publishing applications, and so she took to it like a fish to water. Later in the day, she even tried to copy some of the scripts that my son and I had in place to drive the menu system, in an attempt to integrate the credits screen herself. We had to help a bit here because of the unintuitive signals system, but I give her credit for the confidence.

It was exciting to see how #1 Son was an essential developer on this project. He's been doing jams with me for a few years now, but he has often been something of a legitimate peripheral participant. The last few weeks, he has been excitedly working on some side projects in Godot—projects I have been mostly outside of, aside from the occasional bugfixing tip. For Rocket and UFO Game, he handled a lot of the code himself. Some of this was a bit awkward, such a his first attempt at programming the UFOs. He knew he wanted them to follow a path, so he made them into PathFollow2D objects themselves, with Sprite children. This meant that the UFO scene started with a compiler warning, since PathFollow2D nodes need to be children of Path2D nodes. He was unconcerned but also could not think of another way to do it. I showed him how, instead, we could make the UFO into a plain old Area2D node, allowing it to be tested independently, and then programmatically create the PathFollow2D node as a parent of the UFO when it is spawned. We plan on doing a code review later today to see if there are other places where he can learn some new ideas.

By supper, we had everything in place except for the force fields. I was concerned that, with only about two hours until our deadline, we should probably focus on some balance and polish issues. The rest of the team really wanted to put in force fields, and so we decided to go for it. #1 Son really did all the development on this feature, while I fought with a frustrating bug in the sound system. The takeaway on that one is to make sure you use AudioStreamPlayer and not AudioStreamPlayer2D for your music. That's the kind of kick-self-in-pants idea that is obvious only after spending an hour trying to track down the bug.

We pushed the final version of the game to GitHub at 7:58PM, coming in just under our self-imposed 8PM deadline. We played a few rounds, the high score being, I think, 24 chickens. After that, it was time to get the littler ones to bed, and the rest of us played our worst game of Just One that we've ever done. I think we were all tired and, perhaps, had used up our luck for the day.

That's the story of Rocket and UFO Game. I hope you enjoyed reading about the experience. I definitely encourage you to try something like this with your friends and family. One thing that has struck me is that it's much more fun to make something in a tight timebox than to start something more grandiose and fizzle out. I'm not sure yet what that means for my summer, since I'm still having a hard time getting my head around the impact of my constraints. In any case, thanks for reading, and enjoy Rocket and UFO Game. All the source code is available on GitHub under the GPL v3, so feel free to study it, tinker with it, and learn from it. 

No comments:

Post a Comment