Cattails is a game with a lot of cats. And I mean, a lot of cats. All those cats have different appearances. You name it, if it’s a possible cat coloration, you’ll probably find it in Cattails. As it stands today, there are over 100 unique cat colors present in the game.
Here’s the basic challenge I faced:
I’m a game developer. I have very limited artistic experience. I’m making all the in-game art assets myself.
I need a boatload of cat sprites. And I don’t have the time nor the budget to make that happen by hand.
That’s where GameMaker comes in! There’s a nifty built-in variable called
image_blend that can be used to tint any sprite to any color of your choosing. In order to get a really “clean” version of the hue you’re looking to use, you need to start from a white/grayscale base (otherwise, the existing color will interact with the
image_blend value, and you won’t get the actual color you’re going for.)
So, let’s start with just one blank, white cat sprite (with some gray shading.) Then, let’s tint it using
image_blend. Simple, right?
This works well. We can get a lot of colors from this basic technique. In code, it would look something like this:
Using this value for the variable
cat_color, we’d end up with a cat that looks like this:
Not bad! It’s easy to imagine how this technique could let you color your cat to something a bit more realistic, like orange, gray, black, or brown.
But wait a minute… What about calicos? What about tabbies? What about tortoiseshells and spotted and ticked and bengal? These colors are quite a bit more complex and will require more than just one color to be applied to the sprite.
For reference, this is Elli. She’s our studio intern and resident expurrrt on all things cat. She’s a beautiful calico, which means she has white, orange, and black in splotches all over. How can we achieve a player sprite that looks more like Elli?
One way to do it would be to manually create a new sprite, with the calico markings “hard-coded” to the image itself. That’s all fine and dandy, but it will take some time and we go to create a tabby cat, we’ll have to do the whole process all over. Same for tortoiseshell, bengal, etc. It gets even messier when you consider that the player can face four directions and has unique animations for walking, sneaking, fighting, and sleeping. That would require over 100 hand-made animation frames for each different possible cat color. Yikes!
Our solution came from a technique used in old-school top-down RPGs called “paperdolling”. Essentially, the idea is that you should make sprites for the base of the character, then layer sprites on top of the base to build up a new look for your character. For instance, imagine your player is a knight. You might create a sprite for the base “human knight”, then a new sprite for the “epic gold helmet” that you win when you defeat the dragon mini-boss. You could draw the “human knight” sprite first, then draw the “epic gold helmet” sprite immediately on top of the base to make it look like the player is wearing the helmet.
Now, imagine the exact same process, but instead of a knight, we’re building a cat. Our base layer is the same as before, a blank white cat. But the layers are things like stripes, tail tip, eyes, ears, muzzle, etc. With enough of these layers, we can make some complex cat designs!
The rendering process, behind the scenes, looks something like this:
Each layer can be colored separately. Here’s what the code looks like:
In Cattails, we use 19 independently-colored layers to build up some interesting patterns.
The real power in this technique comes from the fact that, once the white sprite layers have been made, all we must do is supply a few color codes to make a completely new pattern available for the player to use.
In order to organize our cat colors, we’re using two data structures supplied by GML: a
ds_list, and a bunch of
ds_list is exactly what it sounds like: a list of items. We use a
ds_list to store a list of all our color maps.
ds_map is a little more complicated. They are composed of key-value pairs. You can specify a “key,” (i.e. a string,) and that “key” will become associated with a given value. (ex. “Key” -> “value”) It works a lot like a variable! We use a
ds_map for each color to store all of its data in a neat, easily-accessible way.
Here’s what a cat color
ds_map looks like in code:
If we looked at the
ds_map for the “Ticked Cream” color shown above, we could access any individual cat layer’s color by using the ? accessor. For example, if a variable named
ticked_cream_map stores the
ticked_cream_map[? “tail_tip”] would return the RGB color value of the tail tip.
To make things easier on us, we whipped up a little HTML web app that allowed us to visually create new patterns, then export them as GML code (so we can directly copy/paste them into GameMaker).
There are some really neat features in Cattails that were only made possible by this technology. A big part of the game is the romance system, in which you can date & marry another cat and eventually have kittens. Instead of just inheriting one of the parents’ colors, the kittens instead can have some cool unique color mixtures inherited from both parents.
Taking it one step further, the player can then unlock the ability to use their own kittens’ colors, bringing the effective number of unique, usable colors to over 50,000. That’s a lot of colors!
Below are some thoughts on how to make this technique even better. We didn’t have time to implement these in Cattails, but maybe someone out there could use them for inspiration?
Obviously, rendering over a dozen layers to the screen sixty times a second for each character in your game is not the most optimized way to handle things. Perhaps, after drawing each individual frame to the screen once, the game could save a picture of the character image and draw that instead so that it only must draw one sprite per step?
A game could, in theory, allow the player to generate their own unique designs in-game and then share them with the world. We experimented a bit with generating an image file that contained a single strip of color data (each pixel corresponding to one layer to be colored in-game). GameMaker has built-in support to generate these files, save them to the player’s disk, and load them. (See:
Taking the last idea one step further, you could let players upload their unique character designs to Steam Workshop so that anyone around the world could use them in their game. (See:
That’s all I’ve got for you! Feel free to reach out to me @FalconDevelops if you have any questions. Go make some cool games! :)