I don’t have any real development news this week, as I’ve mostly spent the last few days patching Super Win the Game and preparing non-Steam builds on all platforms in order to sell the game via Humble Widget. As a follow-up to last week’s notes on setting up a source control repository, I thought it might be interesting to talk a little bit about how I structure my projects.
Since 2007, I’ve been developing a game engine that I’ve used for nearly every game I’ve released or prototyped in that time. It was clear from a very early point in development that it would be useful to decouple common, game-agnostic code from any one particular game’s source, but the exact nature of this relationship took a few different forms before I was happy with it. The earliest implementation involved creating projects for various subsystems such as audio and rendering, and building a game on top of these. This was a good first step, but many of the features that I put on the “game” side of the game-engine line turned out to be features that I wanted to reuse; these included windowing, fonts, UI, and so on.
The next step was to create a “base game” project which could sit between the lower-level subsystems and the actual (“derived”) game. This layer would handle the implementation of common features while also deferring to the derived game when specific content were required. A simple example is the construction of the game window: a subsystem project provides the code to create a window; the base game uses this functionality to create and manage the primary game window, and the derived game provides the text for the title of the game that appears on the window’s frame.
I’ve been using this pattern since late 2008, after finishing my first indie game Arc Aether Anomalies. In order to keep the common subsystems and base game current for all derived games, I set them up in their own repository which is then included as an external in the derived game’s own source control path.
The most recent change, and one that I’ve waited an embarrassingly long time to make, was to branch the engine for shipping a game. After I finished You Have to Win the Game and began working on my next game (the untitled and unreleased “Project Vanguard”), I ran into a few problems when I wanted to make some updates to YHtWtG and had to deal with reconciling recent engine changes that had broken that game. My solution for dealing with this problem on Super Win the Game was to create a new branch of the common engine code for shipping Super Win. Changes made to this branch as part of post-launch support work can easily be merged back into the trunk, and should I ever need to bring over future engine work for an update to Super Win, I can integrate those changes on a case-by-case basis.
If I were to start from scratch and do it all over again, I think the one change I would make is to keep everything in one repository, with separate folders for each game and for the common engine code. This is analogous to my current implementation, but there’s really no benefit to keeping each of these in its own repository. That decision was mostly born of my unfamiliarity with SVN years and years ago, and while it hasn’t hurt me, it doesn’t offer any advantages either.
I’m not yet sure what the next week will look like for actual game development, as Real Life Things are encroaching on my schedule currently, but I’ll try to find something good to talk about by then.