A fair amount of people have been asking me about the tech used in Atom Zombie Smasher, so I thought I’d make a writeup. It boils down to three main components: SFML, Mono, and something I call BlendoEngine.
The Simple and Fast Multimedia Library provides low-level calls to your system’s audio, input, and graphics. It’s actively being developed, is cross-platform, and is very lean.
Here’s a quick ‘n dirty example of how a sound file is loaded and played in SFML:
SoundBuffer dogbarkBuffer = new SoundBuffer("bark.wav"); Sound dogSound = new Sound(); dogSound.SoundBuffer = dogbarkBuffer; dogSound.Play();
SFML excels at 2D rendering, but also does 3D, assuming you’re comfortable with OpenGL calls. This is my first time with OpenGL, so the most I could muster up with my piddly graphics programming was basic rectangles (buildings, people) and square planes (particles, helicopter).
I use the C# (.Net) variant of SFML, simply because I find the C# language friendly and accessible, and I like its IDE (I use MS Visual C# 2008 Express Edition). The downside of .Net is porting to non-Windows platforms. This is where Mono comes in.
In order for my C# games to work on Mac and Linux, I use Mono. Programs written in .Net can only run on Windows machines. Mono is a framework that enables programs written in .Net to go cross-platform.
A Mono compiler (GMCS) is included in the Mono download package. I use this compiler to make a Mono-compatible executable; this is what the user executes to run the game. I also include the necessary Mono libraries in the game folder, so the user does not need to install Mono into their system folders.
This is the framework that handles “everything else” - gameplay code, UI, resource management. It originated with my first title Flotilla (XNA 3.1), and was further developed and used in Air Forte (SFML 1.5) and Atom Zombie Smasher (SFML 1.6).
BlendoEngine is made up of “manager” components. While SFML provides low-level audio/input/graphics calls, my managers give me a way to more effectively access and utilize these calls. Here’s some of them:
A game consists of a series of “screens.” Screen examples: the Report-a-Bug screen, the end-of-mission screen, the cityscape screen. These screens are placed on a stack; the top-most screen is considered in-focus and is the only one who receives user input. When a screen is done, it just needs to call “this.ExitScreen()” and the ScreenManager will remove it from the stack.
This handles music and sound effects. It is loosely based on Doom3’s sound shader system, though their system has magnitudes more functionality.
Sounds are not called via their filenames, they are called via their sound shader (go to atomzombiesmasher/data/content/data to see the shaders or click here to see an online copy). The AudioManager randomly selects an audio file from the shader. A record of its playback history is kept, so as to ensure you won’t hear the same sound bite repeated again until it has exhausted the entire pool.
For my next iteration I plan to add more parameters, things such as pitch, volume, and randomization weighting.
And the rest
There’s quite a bit more - InputManager, DrawManager, StorageManager, ConsoleManager, UI system, etc. What I love the most is that with each new project, this engine framework gets more robust; the time between starting the project and starting actual gameplay code gets shorter and shorter.
Random technical gotchas learned over the years:
Mono on PC
For Atom Zombie Smasher I made the decision to make all three platforms (PC, Mac, Linux) use Mono, for the sake of keeping all the builds and save files consistent. However, on some specific system configurations, my PC Mono build refuses to start. I still can’t figure out what causes that. In the meantime, using the .Net build resolves it.
Where are you?
Not only is it important to know system specs, you sometimes gotta know what country it is. To separate numbers, some countries use periods. Some countries use commas. This screwed up all sorts of things, including the version updater (i.e. “1.21” was being interpreted as “1,21”).
There are warring camps who disagree on where savefiles & settings should be kept (here is what I ended up using). Barring some official decree, for the PC build of my next project, I think “My DocumentsMy Games” is a more reasonable location.
I found it important (and sometimes difficult) to keep a clear distinction between gameplay code and system (audio/input/graphics) code. If you ever want to port over to a different library (i.e. XNA to SFML), keeping your library-specific code isolated in set areas makes the job much easier.