The Joy of Palettes 2: Multi-coloured Lineart

A new engine, and new possibilities.

When starting fresh with a new engine, we explored a bunch of possibilities, both mechanically and aesthetically. As we were learning how to work with the Z-Engine to make the base for our game, we were also drafting how the game would look; What cues we wanted to preserve from the previous project, and what we wanted to take in a new direction; For example, the characters we worked with in the past had a soft, cartoony look with plenty of bright, lively colors, which we really liked, and which we wanted to keep for this new game.

Having Lauren, and all her years of experience in the cartoon industry to help us with the character designs was a huge help there, because this time, we wouldn’t only be “porting” an existing franchise’s existing designs and making do as best as we could, but we could craft the characters’ look and feel from scratch, to better suit an interactive medium, and a very specific genre such as fighting games, in which a character is presented and known for their unique flavouring; Their individual quirks, their personality, their whole character has to shine through the artstyle and animation in a medium where long exposition and character buildup are not as available as they’re in a non-interactive medium, such as a comic book or a tv show.

And one of the first steps to achieve that was redefining our pipeline to fit both our artistic vision, and to make the process feasible to build from a technical standpoint.

Artstyle wise, we started with the “default” look we could achieve just by importing assets into the engine using the vanilla pipeline. This assumed black lines, placed on top of the colour and shade layers, which allows the detailed artwork and crazy motions of the Skullgirls characters to stand out from their enviroment, while still giving a huge amount of control over the palettes (the different coloured ‘skins’ for the characters), but while the result suits Skullgirls’ very detailed artstyle, the hardness of the black outlines on our characters wasn’t quite giving off the feeling we wanted to achieve. Our goals and methods with the character designs were too different from Skullgirls.

Small Steps.

Mike Z actually showed us pretty early on how to change the lines’ colour from the default black to any other single colour, and it wasn’t too difficult to have the lineart’s color to change from one to another on different character palettes, so we gave that a try. As a result, the characters were softer on the eyes, and we immediately knew this was closer to the direction we wanted to take it on.

Early test with one colour line, and using shade layers to make the eye. Notice the eye is quite blurry.

Early test in-engine, with a single colour line, and using shade layers to make the eye. Notice it is quite blurry.

Having only one colour available, however, was not ideal for our purposes. Different elements of the characters (hair, horns, hooves, eyes, accessories) often didn’t look right when they all used the same colour outline, which limited us to using only darker colours. For instance, we usually want the eye outline to be a lot darker than the body outline so that they stand out more. We tried to come up with some ways around this by using the built-in shade and colour layers, but it soon became clear that we weren’t getting the clean result we wanted out of these early experiments, as we ran into issues inherent to the methods used to construct the final sprites; Line layers weren’t enough for us, colour layers are aliased (jaggy), and shade layers handling it on their own don’t have the resolution to produce sharp lines and the smooth look we wanted for the details.

We sorta let it stew in our minds for a while while we moved on to more pressing problems, like how to set up a pipeline that let us export and convert a bajillion frames from flash, through multiple steps, so they were ready for importing into Z-Engine without causing our blood pressure to increase every time we needed to update a single frame, which would mean having to go through each step of the export process over and over and over again. We eventually solved that issue, but we’ll talk about it in another post.

As we continued working, we went through numerous ideas, including using multiple lines layers (a nightmare when creating and importing sprites, which would also require heavy rework of the entire texture handling process in-engine), multiple shade and colour layers (same problem), and just giving up on using multiple line colours (which made us sad).

Eureka (Sort of).

We eventually came up with a theoretical method to get multiple coloured linework in the engine by using the red, green and blue channels of the line layer, and set to move it from theory into practice.

3colouelinepost5Essentially, every pixel on earth has an RGB value (at least). What we wanted to do was setting the pipeline up so that our artists could make the line layers in flash (our tool of choice), using pure red, pure blue and pure green lines instead of the default one colour, and magically have the engine interpret each one and translate it to a separate palette colour for the character.

One hitch (apart from magic being too expensive) was the fact that the lines layer also takes into account the opacity of the line to give it that nice smooth anti-aliased edge. So the problem was to take a nice smooth image of lines of 3 colours and multiple opacity values and extract that information from each pixel. One of our animators came up with the initial RGB concept and a bunch of maths trying to describe the possible algorithms for extracting this information to our programmers, accidentally discovering the meaning of life, the ultimate fate of the universe and the real secret in the secret recipe in the way.

Being an animator and not programmer, however, certain technical and logistic limitations weren’t taken in consideration, so the algorithms turned out to be too bloated for practical use in the engine. Darn.

… But all this math, not to mention the enlightment that came with knowing the real secret to the secret recipe, sparked our actual programmers to solve the problem properly. Hooray!

Eureka (For reals).

If you think about it as a color wheel, every pixel on the line layer has a position within said wheel.

Its location around the perimeter is the pixel’s colour, and the distance to the centre (white) is how transparent/opaque it is. A pure red pixel (RGB 255, 0, 0) would be located at the red area of the circle (corresponding to a palette colour) and it would be right on the outside (completely opaque). At the same time, a light blue pixel would logically be on the blue part of the circle (corresponding to another palette colour) and closer to the centre (telling us it’s somewhat transparent). A purple pixel -or any non-pure R, G, or B pixel- would be an overlap of two of the colors (Blue and Red in this case) and thus would result in a blend of the same two palette colours the R and B channels stand for. There are only a few pixels in which this happens, but it’s still a necessary consideration to take into account.

A visualisation of how the process decides the information in each pixel. Each one has a colour value and an opacity value that we figure out from the RGB values.

A visualisation of how the process decides the information in each pixel. Each one has a colour value and an opacity value that we figure out from the RGB values.

We sort out the two parameters (where it sits around the circle and how close it is to the centre of the circle) into separate grayscale ‘images’. One image tells the engine what colour each pixel should be, and the other tells it how transparent each pixel should be.

For the colour data image, white means the original pixel was red (of any opacity), light grey means green, and dark grey means blue, (black means none of them). For the opacity data image, white means fully opaque and black means completely transparent (and every shade of gray in between is a partial transparency closer to 100% opaque the lighter it is).

The colour data image is then translated to three palette colours it looks for in specific spots in the palette for each character.

You can see an example of the line colour of a reindeer palette here.

You can see an example of the line colour of a reindeer palette here.

Then this is combined with the opacity data and we get our final pretty antialiased 3-colour lines layer!


So, to recap: We take the original linework layer image, with Red, Green and Blue lines, and transform it into two grayscale ‘images’, one to figure out which color each pixel should be, and one to figure out how transparent each pixels should be. The first one gets translated into the correct color values for each specific palette, and then the opacity data is added to the mix, before we layer the whole result image on top of our color and shade layers, who are way more straightforward than the lines are, giving us our final in-engine sprite. Some false colouring is applied to the colour layers, (as can be seen in images from previous posts), but that’s using the clever already-there tech built into the Z-engine.

All of this put together is our new art pipeline for character sprites, as they go from raw flash assets to the processed, in-engine images that populate the game. We hope you have found our ramblings on colors, maths and lineart informative, or at least interesting!, Next up we’ll have some more visual based updates, most likely on our social media sites, so stay tuned for that!