Programming. Design. Art. Writing.
A profound quartet I stumbled upon during my most recent deep dive into a topic of interest. Like a church bell at noon, something deep within me was struck. Truthfully, my revelatory moment was more a culmination to a slow burn, ignited some time around 2006 while playing Star Wars Battlefront, but a spontaneous and grand epiphany is more fun. Those four words are nestled in the Wikipedia article about Game Jams.
Programming: A powerful skill I’ve been honing for a decade.
Design: Something I always find myself thinking about, from urban design to Mario Kart, I am always wondering why things are made the way they are, what purpose they serve, what statement they make.
Art: An ancient form of communication able to capture the essence of entire cultures.
Writing: A way to sharpen and share ideas, big and small.
My eyes widened and formative events of my past coalesced in my mind like leaves swirling down a drain after a heavy rain. Around, around, and around again, swirling on their separate paths until the moment of convergence. Despite it’s profundity, I’ve had similar moments to this in the past, and they probably each hit me with a similar level of bewilderment, I just didn’t put in as much effort to continue that thread. One such moment came while watching Mythic Quest, a show about a video game company and their trials and tribulations. Though fictional and comedic (and surprisingly dramatic), this was the first time I had a story that captured my attention around game development. Another moment occurred while reading about Edwin Catmull in the book The Culture Code. Here was a real example of someone who has accomplished great things both technically and artistically. A computer scientist, animator, and co-founder of Pixar, known for being a great leader. Bewildered again. And now, Game Jam.
If you are a computer scientist or mathematically inclined, the way I tend to think about moments like this, and the events that lead up to them, is as an upside down non-binary tree. Every node both a leaf and a drain, trickling down to combine and create new insights. Admittedly, I tend to use trees analogously for a great many things in life, so I’ve added a dubious diagram that may address any confusion.
Now What?
I mentioned following the thread above, and how in the past, I’ve had epiphanic moments and then left them lingering at the back of my mind. That’s an easy way to lose information to the tides of time, though, so I do my best to take at least one extra step in these moments: writing it down. I am absolutely positive that my ever-improving habit of writing the damn thing down is the primary factor in my taking a more active role in directing my life and I cannot suggest the habit enough. Though incredible, the brain inexorably loses clarity on ideas and forgets; the bits and bytes composing my notes, on the other hand, change only at my conscious direction (barring catastrophic events).
Ok, so I’ve taken step one, now what? I could join the next Game Jam in my local area, or find one I can participate in remotely. I came across two problems with that. First, at the moment, there are no upcoming Game Jams that I can join, and I find it important to strike while the iron is hot. The second reason is that I have never made a game before. While that’s never a good reason to not try something new, it can be daunting to be the beginner amongst a group of much more experienced people. However, with that in mind, there is nothing stopping me from organizing my own personal Game Jam. It both alleviates pressure and I can start immediately. Cool, step two unlocked.
Parameters
For those who are unfamiliar with Game Jams, they are a lot like Hackathons. And if you’ve never heard of that, a Hackathon is a timed event, usually a few days, where computer programmers get together and work solo or in teams on projects, usually with a theme or a specific goal in mind. A Game Jam is just like that. Between a day and a week and generally following some theme.
Since I have never made a game before, I decided to go easy on myself and make it a week long endeavor. My only other parameter was theme, and at this point, the only Game Jam I’ve come had a one-word theme, so that’s what I went with too. Initially, I wanted to take the time to work on a game idea I already had, but it didn’t feel like that was in the spirit of the jam. Plus, I had grander ambitions for this game than could ever fit in a week, and that was going to add pressure and jeopardize my learning. So, my first hurdle of the Game Jam was to pick the theme. In order to get rid of my bias, I turned to ChatGPT. Before I get to the result of that, I want to emphasize that I use AI as sparingly as I can when doing any creative work, and I generally believe it stifles creativity and learning (a topic for another day, perhaps). If I were to do this again, I would rather phone a friend to give me a theme instead. My opinions aside, this is one of the places I think LLMs shine: as an advanced dictionary / thesaurus. My method was to ask ChatGPT for 10 one-word themes for a Game Jam, verify that it didn’t produce a load of baloney, and then have it pick one at random.
The result? Puzzle.
The Jam
Seeing as I’ve never done this before, I was a bit puzzled (sigh) as to how I should begin. The only thing I knew at this point was that I would be making the game in Godot (you can see more here, but the important bit is that it is a free and open-source game engine). When I want to overcome inertia and start working on something, going to a coffee shop is my signature move. As I often do, I headed to Flywheel Coffee Roasters, my favorite coffee shop in my neighborhood, and frankly, all of San Francisco and quite possibly the world (though I haven’t been to all of them yet).
A natural starting point is to brainstorm ideas. This can be hard to do alone, and my guess is that an organized Game Jam helps with that, but the general rule of thumb I follow for brainstorming is to be as non-judgmental as possible. Depending on your personality, it is varying degrees of difficult to not dismiss your ideas as dumb; you are your harshest critic is an adage for a reason. To skirt this, I use a stream of consciousness method; any thought I have goes down in writing, unabridged, no matter how silly or crazy.
I’ll save you the details of the brainstorm itself and get to the point. The idea I went with was an import / export / shipping puzzle game. The goal for the player would be to fit as much cargo into their container as possible so that they could send it off to another country to be sold. The “selling” would just be an automatic process, through which the player could accrue money and upgrade their temporary storage and shipping container size. Seems fairly straightforward, right? Well, yah, but as will become clear later, I didn’t exactly hit the mark.
A Rough Sketch
My vision for the game was crisp in my mind, and still is, but like most ideas, that sharpness drops like an anchor when it first hits paper. This was the first sign that I had perhaps underestimated how difficult it was going to be to make the game I envisioned (I always knew this to some degree, but the reality of my overestimation is always different from the perceived one). An analogy is perhaps useful in explaining my vision. In the same way that Tetris has blocks of different size that the player aims to fit optimally into the allotted screen space, my player would have to fit objects of various sizes into a shipping container, with the added element of those packages having some economic value. In addition, there would be a designated spot to temporarily store objects at no penalty, allowing for rearrangement. Each round is timed and represents a day (or week or month or year, that doesn’t matter too much). So the player tries to fit as much value into the container, and between rounds, if funds allow, they can upgrade the size of their container or temporary storage. I left it there, but there are plenty of different gameplay elements I felt I could layer from there. The point was, I had a simple gameplay loop with incentives.
I chose not to spend too much time refining my design (as you can tell) because again, I haven’t done this before and I’m not going to magically turn into an expert designer by banging my head on the wall. So, now I had something to work towards that lived outside my brain, imperfect as it was. Onwards!
Placeholder Scenes and the First Functional Piece
Games built in Godot are composed of scenes. A scene is just some element of the game and ranges from the camera the player views the game with to enemies the player fights. Scenes can then have scripts (written in either C# or Godot’s own GDScript language) attached to them which define their behavior; think player movement or how score is kept. This is familiar territory if you know object-oriented programming.
My very first goal was to get some sort of box movement in place, allowing the player to move a box from A to B. This is how I approach development of any piece of software and it’s nothing new. Compartmentalizing a larger piece work into manageable components is a powerful and I love how Godot makes that essentially a natural way to develop (I also watched a Brackeys tutorial on YouTube where he does this expertly; side note Brackeys is a legend). One of the fun things about Godot is that it is not the most popular game engine (yet), so it requires some sleuthing and synthesis to figure out how to do what you want to do. And yah, that can also be frustrating, but what I found is that it was a great opportunity and driver for learning. After a bit of research, I found some helpful information that I could bring together to achieve my goal. The box movement basically worked as follows: drag the mouse over the box, click and hold, drag the box to move it, and release the click to drop it.
At this point, I also found my first bugs. Resolving a bug is another massive learning opportunity, particularly when resources are limited (fixing a bug in Python is a lot different than in Godot). The first bug was that if I moved my mouse too quickly, the cursor would move more quickly than the box and fall out of its area. The result was that the box would stop moving, since the area containing the box had to overlap with the mouse in order to move. I didn’t realize that immediately, but this was indeed a straightforward bug fix. The second was a bit more difficult to figure out but again fairly simple. The bug was that if I had clicked down my left mouse button before entering the area of box with the cursor, the box would start to move after I had then dragged my cursor over it. I didn’t want that to happen, and creating some flags to determine different states of the mouse clicks and movement sufficed in solving the problem.
Though a simple feature, this was a great way to learn about Signals in Godot. A Signal is just that: a signal that is sent by a scene that a different scene can receive and act accordingly. In my case, the mouse passing through the area (Area2D is the name of the class in Godot) defining the box object sends a signal to the “game” scene to move the position of the box to match the the position of the players mouse. Important to keep in mind was that mouse clicks are not automatically enabled in Godot and must be added to the project’s Input Map. I was aware of this, but experiencing that nothingness when I first clicked and then remembering this feature really reinforced the idea in my mind.
And with that, I had my first feature, and was rather proud of the simple mechanic. Now, I wanted to start figuring out how to restrict the placement of the box into a designated area; in this case that would be either the temporary storage or the shipping container.
Improving Box Placement
Dropping a box in a designated location works much in the same way as selecting a box to move by using overlapping areas. There were two types of areas I wanted. One was a valid location to drop a box and the other was an invalid location. Boxes dropped in the latter area would slingshot back to their starting point given they were invalid. I was again fortunate to find useful resources this and cobbled together a solution. One oddity, was that I hadn’t figured out yet how to handle edges. For example, what if a box was dropped partway over a designated area? Ultimately, for simplicities sake, I just defaulted that space to be invalid; a box had to be entirely in a designated area to be dropped successfully.
This is what I call a good-enough solution. I found later that it was a bit flawed (and admittedly still is in the final product), but I knew from the very beginning I was never going to get anywhere near perfection, given my beginner status. Not letting perfect be the enemy of good is a philosophy I do my best to follow and it served me well throughout this mini project (I picked this up from watching CityPlannerPlays on YouTube).
Spawning Boxes
I had more or less figured out the movement of the boxes, so now I needed a way to dynamically bring boxes into the scene. For my first take at this, I kept it simple. I knew (or guessed based on intuition) that making a button to spawn a box at given coordinates would be straightforward. I know how to make a box follow a cursor, so it shouldn’t be too hard to make a button do it, right? Absolutely correct in this case. Despite the simplicity of spawning a box on screen, I nonetheless encountered strange behaviors with collision shapes.
A collision shape in Godot is just like it sounds: a shape with collision physics. This allows my box (also a physics body) to have a floor to sit on when it spawns in. The trouble I had was that every once in a while my box would erroneously fall through the collision shape. A difficult to reproduce error such as that is never good. After some searching, I found that increasing the physics processing rate from its default 60 samples per second improved things. Also, using a thicker collision shape (taller rectangle) for the floor mitigated it further. Ideally, I would have a more robust fix than essentially just using a bigger hammer, but for my purposes that would suffice.
The wonky physics interactions wouldn’t stop there, and I used that same strategy of making larger collision surfaces to resolve those issues too. One particular problem was too sticky to use that simple solution, though. My container and temporary storage areas were enclosed rectangles for the boxes to fit into. However, I did not anticipate the fact that there was no limit to how many boxes I could drag and drop into the areas. When I put one too many in, all the boxes would jiggle profusely until one teleported out of the bounded area. That was a problem I could have spent a lot of time redesigning for or trying to work out some software solution to set box limits. What I ended up going with was rather simple. I opened up one side of the container and the top of the temporary storage, and then I just let the players boxes fall out if they put too many in (those falling boxes will come in later). It’s an easy fix, just not ideal for what I really wanted.
Reaching a Wall
At some point around noon on Wednesday (conveniently halfway through my faux Game Jam) I began to feel like I was so far off the mark that it was almost not worth continuing, or continuing on the assumption that I wasn’t going to have a finished game anyways. This wasn’t a feeling of failure, though, more one of accepting the level of success I had and saving the rest of my week for something else. I had already learned a lot at this point and was happy with what I had done, even though it was all fairly basic. I thought back though to what I felt was the spirit of a Game Jam and also remembered my other philosophy on completing full loops, which pushed me to work towards something I felt was finished, no matter how good or (far more likely) bad it was. I reminded myself that my goal was not to make a fun game, but to learn about game development and Godot. To best accomplish that, it was my opinion that I needed to experience a broader array of development, which is going to include things like a main menu and that end screen I mentioned. My vision for the game and the end result start to diverge significantly here because I had to make concessions.
One of the concessions I made was that I was not going to be doing the art for the background, which I ultimately just left as a stock image of a warehouse. That represents what I wanted it to look like, but doesn’t contribute to a cohesive style. The container was the piece I spent the most time drawing in Procreate on my iPad, and I am happy with the result. Digital art is another skill I am practicing, though it is far behind my programming skills, which mostly means that it just takes a long time to get something I like. The icons for the boxes are also just the default Godot icon that comes with every new Godot project. I used it from the very beginning and figured why not just keep it.
The biggest concession I made in terms of completeness was that I didn’t add any sounds to the game. I wish I would have at least added some placeholder sounds so I would have at least gotten a feel for that system in Godot, but sound design is something I have zero experience in, so that was always going to be challenging. The user interface (UI) is also basic. I have some experience building UIs and have worked with designers, but this is again another challenge for me. Despite that, I am happy I put some effort into getting something in place as I am just a bit more familiar with the mechanics.
With those major caveats to the final result out of the way, it’s time to get to the scoring system.
A Basic Scoring System
Adding a scoring system sounds easy enough, but it involves a couple of different scenes and also needs to all be tied together with the main “game” scene. All of this could be accomplished once again by using Signals. For now, I decided to keep it simple once again and just designate a single point of score for every box that was within the shipping container. I also added in a second, larger box for the player to contend with, but left its points at 1 as well (in hindsight it should have been 3 under this scoring system). My original vision had all sorts of shapes and sizes that the player would have to fit into the container, with varying point (currency) spreads too. But, for the sake of getting a somewhat complete game out the door (this is totally defined by me; I don’t intend to publish this game as is) in my allotted one week, I again opted for simplicity. Later on I added a -1 score for every box that the player lost off the bottom of the screen as a result of over filling the storage area or container. When the timer ended, the score was tallied up. In the end, my basic scoring system is all I did on that front, but I did add in a high score in the end screen.
A Few Final Pieces
I have to be honest, at no point did I envision the the onus would be on the player to spawn a new box by pressing a button, but alas, that was another one of my concessions in the final game. Since I had decided to just leave that clunky feature in, I knew I had to at least improve its functionality. Initially it just spawned a single box type, the smaller of the two that I had. So, the change I made was just to randomize which type of box would spawn. It’s simple enough from a technical standpoint, but isn’t quite the sequential auto-spawning I imagined (again, similar to how Tetris displays the next piece before it automatically slides onto the screen).
I also at this point moved around the placement of the designated drop areas so they made a bit more sense, although a big driver for their placement was that wonky physics action I mentioned earlier. That was one of my key takeaways from the Game Jam: sometimes you make the design decisions and sometimes they sort of make themselves. I imagine that becomes less and less true the more game dev experience one has, but for me, that kept coming up and moving things in a different direction from my intention.
Final Thoughts
I am proud of the game that I built and happy with the overall result of my week long Game Jam. I want it to also be crystal clear that those feelings are not a product of disillusionment that the game I made is good. I actually think (know) that it’s terrible as far as video games go. I am unshaken by that, though. All I wanted to do was go from 0 to 1 in game development and I know I’ve done at least that. I also had some of the most fun programming I’ve had in a long time, probably due to the immediate and frequent feedback I received as I worked on each new feature. Game Jams are on my radar now, and next time I might participate in an official one and learn from people who’ve been doing it for years.
Other Meta Thoughts
With each blog I’ve written, I do my best to try something new. This time, the big difference was adding in videos. It’s probably been over 15 years since I last uploaded a video to YouTube, so it was interesting to see where the platform stands now. I wasn’t initially sure how I wanted to embed the videos, but outsourcing the resources for video playback quickly proved to be the best option since it reduces the amount of stress my website takes on. Plus, I’d been wanting to do something with YouTube for quite a while, and now it’s another skill I’ve taken from 0 to 1.