The graphics pipeline in Dawn of Man
Dawn of Man, the RTS I finished a year ago, had a rather convoluted process through which sprites went, from source bitmaps to what players see on the screen. The overall process took place over the course of the entire development, with irregular additions, enhancements and optimizations as I better realized how I wanted the thing to look.
We start with two files, describing the shape of each object, and its background mask. Each unit, building and decoration has these two files in the program directory. In reality they describe each frame of animation for each object, but for the sake of clarity here we’ll simplify them to individual frames.
A friend once told me “remember that you’re making a game, not an engine”, meaning that one shouldn’t get too distracted in making everything reusable and modular at the cost of completing the game. When it came to the colors of units in Dawn, however, I considered it important that the colors not be “hardcoded” into the source bitmaps – not just because of the pain that changing or adding a color would cause, but also because I envisioned that different levels might use different colors from each other.
To make different colors of units, I created in memory a rectangle, the same dimensions as the image file, and filled with the color I wanted. Then I just drew the image file onto it with magenta transparent, effectively switching from magenta to the desired color. I also did this for the light- and dark-grey colors for the edges, which create the carved effect of my sprites. Then, for each player color, I just drew the two grey images onto a green background, at (-1,-1) and (1,1) offsets, then drew the colored image on top.
There are a lot of possible combinations; each unit and building, in each color. If combined beforehand, many images would likely have gone unused, and if the game had ended up with a larger collection of objects, this would translate to a lot of wasted memory, plus unnecessary delays at load time while everything was drawn. On the other hand, combining everything as it was drawn would have been too taxing on my limited economy of CPU cycles. My solution was a three-dimensional array of null pointers. When an image combination was needed (i.e. the render function was called, and that image was requested) it was either pulled from this array, allocating and drawing if that hadn’t been done yet. The end result performs well, and doesn’t use any unnecessary memory (apart from the extra 0s in the array).
Originally, the image files included the carved edges. However, I decided to add these edges in the code too: I might have wanted to change one of the shades of grey, or possibly make them farther than one pixel away from the image itself. I didn’t end up changing either of these, but adding the functionality fit quite well into the player-color structure already in place, and so it wasn’t a huge investment of time.
The big hurdle to which I came was that the units generally had transparent chests and heads, meaning other units were visible behind them. If this were an actual cave drawing, this wouldn’t happen, and these cavities would have solid rock underneath them. What I eventually decided to do was use masks (as seen in the other image files above), and draw them underneath each sprite. The process itself is probably best described graphically, so here’s how it works:
And, just for fun, here’s everything together:
Complicated, yes, but in the end I was able to get the exact effect that I wanted. I’ve often considered how I might implement a 3D version of Dawn, but I think the transparency issue would be one of the more challenging ones. In that regard, 2D is superior… which is nice, considering that one of the original artistic goals of this game was to create something where 3D would not be an obvious direction of improvement.
Since this project I’ve also played around with alpha channels and pixel-level manipulation. I suppose this is all the fun stuff that the sprite-wrangling developers of the ’90s got to play with. I envy the folks who got to develop new techniques for Tiberian Sun, Age of Kings and Diablo II, but I suppose there’s even more to play with now, in 3D. I just have to take off my Rose Tinted Specs.