Generating Tile Images III (GameWorld 12)

Time for the next level in tile-generating :).

Last time we looked at generating a range of simple shapes, like balls, trees and bricks. This time around, I am adding a new range of filters to the tile maker, so that you get rid of that cartoony look, at least a little bit.

It is but a single step on my enormous quest to generate nice-looking tiles without having to resort to pixel-painting ;).

Dither

This first one is simple. You pick a color, and then sprinkle x% of the tile with that color at random.

It's a very useful technique, and in retro RPGs you will often find dithering in grass tiles, water tiles or sand tiles.

Dithering as it was used in Mystic Quest. Courtesy of *Hardcoregamer.com*.

To do dithering we first have to have a randomly shuffled list of all pixels in a given tile. You can do that using this function:

def random_pixels():

# build a list with all the pixel coordinates.

pixels = []

for x in range(48):

for y in range(48):

pixels.append((x, y))

# randomly take elements from the first list to build a second one.

pixels2 = []

while len(pixels) > 0:

i = random.randrange(len(pixels))

pixels2.append(pixels[i])

del pixels[i]

return pixels2

Now, randomizing becomes quite simple, because we just take a bunch of elements from our shuffled list of pixels. To make using the function easy, I define an intensity parameter, which can be set between 0.0 (0% dithering) and 1.0 (100% dithering).

Now using the building block above, and my previous code, I can make a dither function like this:

def dither(t, i, color, intensity):

d,x,y,tw,th = t.get_properties(i)

coords = tp.random_pixels()

threshold = int(len(coords) * intensity)

for j in range(threshold):

xj = coords[j][0]

yj = coords[j][1]

tp.pixel(t, i, color, xj, yj)

Here is an example of a simple dithered tile:

And you use the following code to make it:

tp.draw_plain(t, <tile_index>, "#999")

te.dither(t, <tile_index>, "#222", 0.1)

Noise

A Noise filter distort colors, e.g. it can turn a blue square into a square with varying types of blueish colors. In the most extreme case, you can get tiles with simply randomly colored pixels everywhere.

To distort colors of a single pixel, we can use the following:

def color_noise(rgb, intensity):

intensity *= 255

distortions = (int((random.random() - 0.5) * intensity), int((random.random() - 0.5) * intensity), int((random.random() - 0.5) * intensity))

return constrain(rgb[0] + distortions[0], rgb[1] + distortions[1], rgb[2] + distortions[2], rgb[3])

Once again, an intensity of 0.0 is no distortion, and 1.0 almost complete distortion.

I then made a color_filter function that simply applies a function like this to a full tile:

def apply_color_filter(t, i, filter_func, intensity):

d,x,y,tw,th = t.get_properties(i)

for xi in range(0, tw+1):

for yi in range(0, th+1):

color_hex = tp.rgb_to_hex(filter_func(tp.get_rgb(t,i,xi,yi), intensity))

tp.pixel(t, i, color_hex, xi, yi)

Right now I only use it once, but I figured I may be needing something like this in the future ;).

Anyway, this then makes the noise function quite easy to write. Here it is:

def noise(t, i, intensity):

apply_color_filter(t, i, color_noise, intensity)

Noisy tiles can then look like this:

Now that could work reasonably well for a sand tile, right?

It could also look like this, if you go on full random by the way ;):

Closing thoughts

But wait! At the top of the page you can see even more tiles, right? Indeed, I also developed an effect to add a drop shadow, a top highlight, and even a generator to make random stony patterns (that one took AAAAAAAGES by the way!).

But adding those here would make this post a bit bulky, so I will be sharing those somewhere in the next few days :).

Until then, please do let me know if I could explain any part of this tutorial more clearly, as I'm happy to make changes.

Lastly, I have a working repl.it of the tile generator (including early versions of the additions explained in the next blog post!) here.

Continue reading with a Coil membership.