One of the main issues of my little game-studio is that we lack a proper pixel-artist. While we tried to team up with some artists we had no luck with finding one that works reliable and wanted to take the risk of doing work without knowing if we make money or not.
So i decided to research methods of producing pixel-art myself. While i am not a great pixel-artist, i have a deep interest in procedural generation. Inspired by the work of Dave Bollinger i came up with some experiments that i wanted to share here:
So how does this algorithm work?
The basic idea is to use a mask that provides information where to paint pixels. My current setup is using only 3 possible states: 1) always paint a pixel here 2) never paint a pixel here 3) paint / not paint based on randomness
The second important thing is that we only construct half of the image in a random way, the second half will get mirrored.
In the above example, each image is 64×64 pixels, wich means the base mask is 32×64 pixel (i am only mirroring at the y – axis)
In this first step we only gather information if we paint a pixel or not – nothing more.
The next step is outlining the resulting shape, wich means painting black around the borders. This is fairly simple: we just check if a pixel is not painted (we dont want to override the existing shape) and also check if there is a painted pixel in the “von Neumann” – neighbourhood wich means the 4 cells orthogonally surrounding our current cell.
If both equals true we know we found a valid border and paint it black.
Now, cause of the randomness we will face lots of 1 pixel “holes” in the interiour that we as a human might recognize as beeing inside the resulting shape. Those will all get outlined black, resulting in lots and lots of black pixels. One solution is trying to recognize whether we are painting a border on the “real” outside or not.
To test this we just check if we find cells in the “von Neumann” neighbourhood that are marked “not painted”. If we dont find any we can mark this cell as “inside border” (and treat it different later in the coloring process) – else we know its an outside border and can be painted black.
Another step that helps reducing “noise” in the final image is to delete single pixels that are completely surrounded by “not painted” cells in the “von Neumann” neighbourhood. This step have to be done before the outlining process.
Till now we just produced a black/white image. To add coloring i used the idea from Dave Bollinger outlined in his PixelRobots tutorial.
The main idea is to use the HSB color space (Hue, Saturation, Brightness) and map saturation according the Y-Axis and brightness according to X-Axis.
I came up with my own modifications to this algorithm wich mainly extend it and let me define minimum and maximum values for all 3 parameters.
To get structure into the shape i use the previously gathered information about “interior” borders and color them similar to normal painted cells, but reduce the saturation and/or brightness to let them stand out.
Till now we just processed half of the final image, the last step is now to mirror it along the Y-Axis and draw the final texture.
A nice coloring trick here is to slightly reduce the brightness and/or saturation in the mirrored image to further improve the lighting on the final image.
While this algorithm already provides nicely colored shapes there is plenty of room for experiments.