[Quack V: Omelette of Doom]
ArticlesArticles
 
[SeaLeft Studios]

Postmortem: Quack V: Omelette of Doom
By Richard Hoover

The History
I’ve always had an interest in computer games and in computer programming. As such, it was only a matter of time before the first game set in the world of Cubes would come along. My first idea for a game was actually based on the characters from the regular Cubes strip itself. However, I decided that I should instead do one or two “little games” first to develop the backend programming framework needed for a more complex game.

I had several ideas for a number of mini games, but ultimately settled on Quack V for the following reasons:

  • The game was going to be a classic first person shooter with only rudimentary story elements. Such games are pretty limited in scope and require relatively little design-wise. I didn’t want to split my time between designing new game play and story elements with developing the backend.
  • The game was complex enough that it would have all the pieces that a larger game would require: graphics, audio, state handling, resource management, control mapping, etc., etc.
  • The boss enemy for the game was going to be the Scrambler. I liked this idea as it tied the game in with Hot Dog issue 2, where the Scrambler also appears.

Armed with a couple of pieces of scrap paper with some “design” notes on them, I began actual development on Quack V in March 2006. My first goal was to get the 3D virtual environment up and running as fast as possible. This didn’t take long, as Quack V is essentially just a 2D grid like maze extruded upwards to give the walls some height.

Once I got the basic map loading and rendering done, which only took a couple of evenings, I began the process of evolving the project into an actual game. I didn’t have much of a design and was more interested in getting the technical pieces all working. This meant that the game was put together rather haphazardly, with work being done on different parts as the fancy struck. In some places this worked well, in others not so much.

The Not-So-Good
Most of the road bumps that were encountered during development came from the lack of planning at the beginning. Due to various “because it’s easy” decisions made early on, I had to rework major portions of the game code several times as the game came together.

When I first started on the game, I wanted to get stuff up on screen and moving as soon as possible. This led to the mistake of tying game state updates directly in with the game rendering. Basically this meant that every time the game updated the scene on screen, it would also do processing to move enemies around, respawn items that had been picked up, and perform animations. At first this seems like a natural way to do things; however, problems quickly became apparent when I started fleshing out other aspects of the game.

In Quack V when a level ends, either in victory or defeat, I wanted to have the action pause on screen. I also wanted to give the player the ability to pause the game. Plus there was the options menu that a player could switch to while playing. I added each of these different things in one-by-one and as I did the code became riddled with special conditions. For example, it was like saying "do the animation but not if the game is paused, or the player's won or lost the level, or the briefing is being displayed, or..." Each time I added in another one of these conditions, the code got more cumbersome and more fragile.

Ultimately I ended up pulling the code apart so all the processing stuff was done separately from the rendering stuff. At the same time I introduced a state management system. Basically each game state (game paused, level won, level lost, etc.) was responsible for doing its own processing and rendering. This meant that each state did the minimum amount of work necessary (always a good thing). It took a few evenings to switch the code over and debug it to make sure it worked in all situations.

The next problem I ran into that required significant rewrites happened very late in development. Through most of development I had just been testing the game on my Windows XP based machine. It had been running really well and all the animations were correctly timed to run smoothly on my machine. I hadn’t tried it on other machines because I hadn’t created the unified file handling module discussed later in this article. As a result, I had several dozen files scattered around for things like textures, sounds, and levels. Having all these different files made it really difficult to move the game from one machine to another.

When I finally got the data files under control, I moved the game over to an older Windows 98 system. When I ran it on that I found that everything was still running smoothly but at about a third the speed it should be. When developing the game, I had used a simple timer to control how fast the animation was running. Windows XP provides access to a fairly high resolution timer that was able to run fast enough to keep the animation and movement through the game running at the correct rate. Windows 98, however, had a timer that was only good for up to about 18 frames per second, which wasn’t anywhere near fast enough to run the game.

So for my second major rewrite I had to go back through and take out the timer. This meant that anything that had previously been depending on the timer now had to be changed so that it would check the current time and compare it to the last time it had updated and then move accordingly. So say you had computer A running five times faster than computer B. For B to present things at the same speed it would have to move things five times as far. It was a lot of work to switch the game away from using a timer, but it meant that regardless of what computer the game was run on the action would run at the same rate. The moral of this story is to never, ever use a timer!

The final rewrite to the code came at the end of the project and was more of an experiment to learn things for future games. I had originally written the game so that everything happened all in one thread. As an experiment I took a copy of the game and changed it to be dual threaded.

I wanted to do this experiment because, in reviewing the game code, I found a lot of effort was spent on dealing with the fiddly bits of Windows programming instead of the actual game programming. This was for things like setting the screen resolution back to the right size when the player tasks out of the game, restoring the game resolution when they come back in, dealing with the game being closed by means other than the built in “Quit” option, etc. I basically ripped the game in two and placed all the code that had to deal with Windows in one part and all the code that actually ran the game in another. Due to how the code ended up being split I had to rework major parts of the game including some of the framework pieces I’d been developing. Any future games I make I’ll be sure to have dual threaded to begin with.

Another significant error I made during development had to deal with the music of the game. As far as game development goes, I’m at least decent in all areas except for music composition. I naively thought that if I built everything else in the game that I’d be able to convince somebody to do the music for me “later on”. I kept pushing back the music thinking that I didn’t need it yet. Suddenly, I was at the end of the project without any music and unable to convince anyone to help me out in the timeframe I was planning. I pursued several different avenues of trying to get the music before finding a software package that allowed me to do some half decent tunes myself (being a complete music illiterate this was more challenging than you might think). Due to the problems with getting the music in place, the release of the game was actually delayed several weeks longer than it should have been.

The Good
Although I wanted to end up with a game at the end of the day, my main goal for this project was to build the infrastructure that would allow me to more easily make larger games in the future. Towards that end, there were several modules that I created that I thought worked out really well and that have given me ideas on how to improve the rest.

One of the things that I’m most happy with in the game is the virtualization of game controls. I wanted to create a fully featured game and one of the steps in this was to allow players to remap controls to their liking. As far as controls are concerned, the game itself shouldn’t have to worry about whether the player presses a button on the keyboard or moves a mouse or joystick. All the game should have to do is ask things like “does the player want to move forward?” I wanted to give players total freedom for what controls they use. In the system I developed, the player can just as easily map a mouse move to an action as they can a keyboard button (which, when you think about it, are two radically different input methods). The system works well and has the benefit of hiding all the gory details of dealing with Windows input events from the game itself.

The second piece of the framework that I was really happy with was the audio module. The audio component is built on top of OpenAL, which is a nifty audio library that handles all the hard work of playing sound in 3D space. OpenAL has the idea that you have sounds that can be played and you have emitters where those sounds are played from. The trick is that you can only have a limited number of sounds loaded and a fewer number of emitters available. For the audio module I developed some resource management routines that allow you to say “I want to play sound so-and-so at location such-and-such”. The audio module then loads the sound if needed and finds a free emitter to play it with. Based on the type of sound being played, each sound has a different priority level (for example you always want background music going so it’s got one of the highest priorities). If all emitters are currently in use, the audio module sees if there’s a lower priority sound being played. If there is, then that sound gets the boot so the new sound can be played instead.

Due to how much needs to be handled internally by the audio module, I built it in such a way that it automatically manages the audio resources so that the game itself doesn’t have to. This takes care of everything from loading the sounds from disk, to playing them, to cleaning them up at the end. All programmers know what a hassle it is to manage resources, so having something that takes care of them automatically is a big plus. This is a concept that I intend to incorporate into all aspects of the game framework for future projects.

As development went along, I started having all kinds of little data files kicking around everywhere. Image files for textures and sprites. Audio files for the sounds. Level files for the maps. Having all of these as separate files was great for development as I could make changes to any of them, fire up the game, and see the results immediately. However, I knew that for the final, downloadable version I didn’t want all these files floating around loose. I wanted to get all the separate files into one big archive file.

To address the file situation, I wrote a set of file handling routines that the game side could call without having to worry about whether the file information was coming from a separate file on disk or from a big archive file that had all of the data files compressed into it. I wrote the file module such that it could be configured to prefer reading files from either the archive or from disk. This allowed me to read files from disk during development then just change one setting to read from the archive for production.

Taking further advantage of the division between archive files and disk files, I set up the module such that if you requested files to come from the archive over the disk, then any files that did come from the disk got logged in a separate output file. This worked really well because it allowed to me to ensure that all necessary files had been included in the archive for the distributable version.

Looking back, with the project completed, there were more than just technical successes in the game. The biggest success was a more personal one. Lots of people get the urge to try and make a computer game. After a week or a month of heavy work interest begins to flag and the project slowly dies. This unfortunately happens to the majority of independent game projects out there.

What I found that really helped me was to say “I am going to work one hour a day on this game.” An hour isn’t really much of a time commitment when you think about it. During development of the game I kept track of my hours and of how much time I owed if I missed a day here or there (which happened at various points for various reasons). I also made the rule with myself that if I worked extra hours in a day, then I wasn’t allowed to count that as a credit for days that I might miss in the future (i.e. I wasn’t allowed to say I’d done tomorrow’s work today). I found that this really kept me focused on the game and allowed me to weather those periods where the game’s “to do” list seemed overwhelming and my interest started to fade.

The Future
Development on Quack V began in March of 2006 and finished in December of that year. I surprised myself by just how much I could get done working only an hour a day for a few months. This has really encouraged me to want to make more games in the future.

Quack V is a fun little game and a worthy addition to the world of Cubes, but it was always primarily intended as a test base for creating a framework to use in future games. After finishing Quack V and looking at the various framework modules, there are some pieces that I really like and really work well and there are others that I can now see some really great ways to improve. Now that the bulk of the framework is done, the majority of the generic game technical problems have already been completed. This means that on future projects I’ll be able to focus more on the unique game aspects themselves rather than the technical details of presenting the game.

Quack V was a good starter project because it was small enough that I could keep all the details in my head without requiring a big design document, but also complex enough that it covered all the major game tasks that must be performed. I’m looking forward to building on this success with a game featuring the characters from the semimonthly Cubes strip itself.

Back to Articles


Copyright © 2003-2024 by Richard Hoover. All rights reserved. No reproduction without permission.