Programming "Admin" - 1 Week In

Hey folks,

I'm the programmer for a team of a 3 on a point-and-click game we're titling "Admin". This is my first game jam, and I've learned a bunch along the way. I am new to making games, but I have been working as a programmer for about 10 years. I've been wanting to codify the things I've learned over the past week, and I figured it'd be cool to share that to other folks too. In particular I'm interested in how we've distributed work, what has worked/has had to change, and also the technical parts as to how we're scaling our game with content. I've been using Godot for all development and will be heavily referencing it. ## Days 1-2: Ideas & Prototypes

Our team is made up of a writer, an artist, and a programmer (me). The other two folks have been in game jams before, but it is totally new to me. Our first days included opening a Discord and sharing Google docs. We spent ~1 day or so coming up with the idea for our game. Our main criteria was to stay on theme, so we started by braindumping anything that the theme brought to mind whether that be words, sayings, game ideas, things you could do. Searching Wikipedia for "locked" was actually super useful and wound up tying back to most of our ideas. In the end we decided the game should either be a puzzle game or a platformer game. Eventually our writer had enough passion in an idea that he was able to drive the idea home, and we landed on a point-and-click game where you play as an IT Admin whose goal is to unlock peoples' computers for them (they've forgotten their passwords). I think this wound up being a great idea for our team - especially because each of us could focus on our own areas, and each of us could make a substantial contribution with our skills.

Around day 2 we started defining the tone of the game by sharing reference games. We also scoured the web for pictures that would be similar to what our game looked like. We found an image on Google that looked roughly like what we wanted - a pixel art business office and we ported this into Godot to make a quick prototype. The prototype allowed me to figure out how to make a point and click game quickly. I was able to share videos of the prototype via YouTube. At that point our motivation really kicked in. Our artist started making tilesets and designing the rooms, our writer started writing up level designs, and I... well I mostly screwed around and made silly things like a mock Google search engine.

## Days 3-5: Initial Integration & Friction

While I was busy toying around with easter eggs, our writer produced some draft levels and our artist produced a bunch of excellent tilesets. I started to rebuild our prototype level with the tileset components and also started building some of the other interactive elements our script called for. Here's a demo. The code at this point was getting a lot more complicated. Our dialogue script is fairly involved. It calls for items to pop-up at specific times, has a choice system, and has hidden choices that are only available if you've done other things in the game. One of my core goals from the onset of the game was to keep as little in the game hard-coded as possible. Given we were going to have a content-heavy game, I thought I would go mad if I had to maintain a lot of specifically configured nodes inside of Godot. Instead all of the dialogue and configuration in our game is defined in static data files and loaded by the game at runtime. These files are parsed and create all of the event listeners and configure all of the nodes. My original hope was that our writer would be able to write these  config files and I could focus on the implementation side of things (but that idea did not work!). I had to convert and edit all of our Google Docs content very specifically in order to get it to parse properly in Godot, and this wound up becoming a huge headache which I'll take about more soon.

Another thing we'd started doing was importing all of the assets (tilesets, props, characters) into Godot. I would assemble levels and then post them back into Discord for review, tweak, post, tweak, post, etc. This back and forth wound up taking a lot of time, and the team had a lot of feedback to give. Scaling sprites and CollisionShapes in Godot was a surprising amount of work, and I eventually asked if we could instead just import pre-built levels as single images. This way our designer could work quickly in Photoshop without having to deal with issues like Nodes and CollisionShapes and I could get more time to focus on building the foundations for the interactions our script needed. This wound up working brilliantly and saved everyone a lot of time. Our designer was able to spend a lot more attention to detail and came up with some very creative work that fits our script like a glove.

## Days 6-7: Complexity & Still No Complete Levels

One of the things we did early in the project was establish goals to separate "must-have" features from "nice to have" features, and one of our "must-haves" was to have 5 levels, so it was alarming when a week had gone by and we still hadn't gotten a full level completed. Our focus for this past weekend has been reconciling this, and we've thankfully been able to complete a title screen and two levels this weekend. Part of the issue was simply work management and the nature of the chaos that is a game jam, but I'd also like to talk a little bit about the technical side of things here.

One of the things that became clear early on to me in the project was that our script required a very complex dialogue system. In particular, we wanted to be able to do things like insert a choice mid-conversation or zoom in to a character or pull-up a close-up of a sticky note. We wanted some options to only be available when other things had been explored, and we wanted repeat visits to NPCs to have different results. Our configuration file which defines our first level is over 400 lines of code. Converting our Google Docs to these files has been an enormous chore, and reasoning about these files has been very difficult. Our intro sequence alone for our first level winds up creating 28 nodes! These define code for zooming in, presenting choices, branching, adding animations, etc. After writing level 2 (which was a lot more complicated than level 1 - at almost 700 lines of code) it became clear that this wasn't going to work out. After trying several solutions I eventually decided to write some Ruby scripts to generate our config files. I used the `diff` shell command to make sure all of my new Ruby code generated the exact same files I had developed by hand. Ruby is more expressive than INI-style files, so this allowed me to create helper functions to refactor the code into something a lot more manageable. I've also been able to add checks to make sure required fields are defined before I test them in Godot.

Another thing worth talking about is how I am building the levels. I've written a lot of data-driven code that uses conventions to streamline the lookup of associated files. For example, the code looks at the level file's name to figure out which song to play or which data file to load, so Level1 will load the Level1 music and data. This way I don't need to update any of the plumbing when things change, and this has been a huge time saver. Additionally, our Core code searches for every Area2D (which we make during level design) and tries to match that by some simple naming conventions back to the code defined in our data file (for example the "boss_computer" data will always correspond to the "BossComputer" Area2D for click detection). This saves a ton of time and makes it very easy to figure out exactly where we need to look when an issue arises. We do this with a few other things, and it winds up turning the data files into powerful scripting tools where we barely need to do anything in Godot to create a new level.

The last thing I want to mention is how we've streamlined our build process. We started deploying releases to HTML5 to a restricted project very early on (this was super important and caught a lot of bugs that would've been impossible to track down if we had found them after having thousands of lines of code!!). One of the problems was that this was starting to a lot of time. I had to go into Godot, click through the export UI, pick HTML5, compress everything into a zip file, log-in to itch, drag and drop the file, post in Discord. Hopefully I didn't find a bug, or else I'd spend another 5-10 minutes on this (and another... and another...). One thing I did was create a build script which exports to HTML5 and uploads the file directly to via the butler tool. This has been super, duper useful. Now whenever something remotely interesting is completed, I just run ./build and everything gets pushed to After it loads then I can share it with my team for feedback. It has also made it a lot easier to find bugs that only affected HTML5 - we could go back in our git history, deploy a new build, see it was still broken, etc until we found the exact commit where the issue was introduced.

So far I'm super happy with how our project has been coming along - even if there were some grindy/annoying parts. The biggest lesson I've learned is that it's important to understand what you are wasting your time on. Should you keep grinding away on time sinks, or should you invest time to remove these time sinks? For me, it wound up being very worth it to invest time to make things better. Some of the features we wanted in our dialogue system would've been very difficult to build otherwise and we are setup nicely to quickly make lots of additional content in the future if we need to thanks to figuring out how we can scale/streamline our content-heavy game

Leave a comment

Log in with to leave a comment.