18 elemental textures

I have a personal interest in generating textures based around the 18 elemental types from the pokémon games. My last attempt was not particularly good. This time around, having a better grasp of procgen methods, I am quite happy with the results.


The eightteen types are all, of course, described by a colour, but I would not be satisfied for them to just be colour-swaps of one-another. To distinguish them, I will apply a secondary colour tint to each of them with a procedural texture matching the type. For a type like fire, this is quite obvious, but what about fighting? The next question is to then generate this texture using Perlin noise and math. How does one Perlin-generate a flame?





Water has white as a secondary tint, which is used here with a very horizontal Perlin noise to show glimmering waves. This noise is only shown where the values cross over a certain threshold, which creates these disparate bright spots.

The background here as with all the others textures showcases a simple noise texture. All noise is domain-warped to create more interesting, fluid textures, which, coincidentally, works quite well with water.


This is an example of the domain warping, which, really, is not exaggerated. Don't pay attention to the seeming higher frequency of the example to the left, this is just a side-effect. Rather, the difference is the much more complex, fluid-like or sinewy textures that appear in the domain-warped noise on the right side. At this point, I add this into any noise function almost without thought. It just works that well in most cases.





Poison is supplemented with a dark and a light green, another common signifier for poison - which also plays well with all the grass-poison dual-type pokémon. The texture is a domain-warped contour map interpolating from purple, to dark green, to light green, to purple, the further the Perlin value is from zero.




Normal is one of the types with a not-very obvious texture. The two colours used are a dull beige/grey and a lighter grey. Here, I have opted to overlay Perlin shapes created by colouring in any value above a certain threshold. These shapes utilize very strong domain warping.





Psychic is number two of the five purple/pink types. Its secondary tint has therefore been chosen to be a brighter pink. It does not actually have a unique texture, only the background noise, though this has been amplified. The background noise is common to all types and interpolates the primary colour with the secondary colour, with an emphasis on the primary colour. It also features a gradient from top to bottom, which explains the effect seen above, where the top and bottom are mostly evenly coloured (primary at the top, secondary at the bottom), and in the middle, the Perlin noise reigns.





The Dragon type is canonically purple with orange as secondary colouring. I have instead chosen teal, as it plays better in a texture that should not be too distracting. The scaly texture is produced by calculating the distance from each pixel to a |sin(x)| function, which is modulated by y to repeat and warped by the square horizontal distance to the middle to create the curves. The curves are shaded by seeing if the distance is in the positive or negative y direction. Finally, the big difference in hue between the primary and secondary colour creates a neat vertical gradient (as described above).




The grass texture shows off grass! What! My last attempt instead used vines, like seen with the Poison type, but this is so much more obvious. The grass uses a 1D Perlin noise using the x-coordinate. This, then, is warped slightly by sin(y+x), to create the wavy feeling. It does not look perfect - you can see a diagonal artifact if you look for it, but on the card, you'd never notice.

Generation 1 only has a single monotype grass pokémon. Most instead are dualtype with poison, where cards would look as above. Dualtype cards take one type as the inner ellipse and another for the outer rectangle. The colour combinations can create quite interesting dynamics.





Ground needs to both be similar to but different from the rock type. Thus ground has a sandy yellow as secondary tint. The same method is used as with normal - Perlin shapes by using a threshold - though the threshold is lower and the x-coordinate is exaggerated to create more flat shapes. If I am to redo this, I would put more emphasis on the texture, since it is a bit difficult to notice.





Fire! The poster-boy of the project and the most obvious texture. The secondary tint is a pale yellow, and is applied with noise exaggerating the y-coordinate. This noise value is added to the y-coordinate, meaning that low noise values at the bottom are as bright as the high noise values near the top. The total effect, including the colours, is that the card is figuratively on fire!

Though fire was one of the most succesful of my first attempts at textures, the difference is obvious. Not only because you almost can't see the colours in the above, but also because domain warping is quite important to make flames look like flames.




For Bug-type, a web seemed like the most obvious texture. Like the dragon type texture, it relies on a complicated function computed for every pixel. This one first takes the distance from the centre to find out which ring the pixel is part of. Depending on the ring, how many curves the ring should be seperated into is decided. Then the direction is modulated and absoluted to find the radial distance to the closest peak. Finally, how concentric each curve is is decided by the current ring and a set random value relating to the index of the curve. On the inside of the curve, a short white gradient is applied. On the outside of the curve, a subtle shadow-gradient is used instead. And that's it. Phew.

Though the rings are white, the actual two colours of bug are lemon and lime respectively, as can slightly be seen in the gradient from top to bottom.




Rock is the third use of the Perlin shapes using a binary threshold, though at the very least, the shapes are quite different since it uses different arguments. The two colours are brown and a darker beige/grey.

Some pokémon, like geodude and graveler above, have had their types altered slightly to reduce the number of overused dual typings.




The flying type is one of four types that all want to hog white as their colour (normal, flying, ice, steel). The primary colour is a dull teal and the secondary white, of course. The clouds are also Perlin shapes using a threshold yadda yadda yadda, but there are actually five thresholds each with their own opacity, creating more fluffy, cloudlike shapes. Also, domain warping is toned way down.



The fighting type is one of the ones I am most proud of. The secondary colour is a red mahogany applied by Perlin noise with a radial pattern. This is accomplished by having a weak influence of x and y coordinates and a high influence of the distance from the centre as the third dimension in the noise formula.

I finally found a way to use this.



The electric type is so-so. Again, we have a Perlin contour as texture, only with an x-gradient applied which creates repeated horizontal lines. I tried a lot of other methods, but with the challenge being to generate all colour effects within a single function call, I was not intelligent enough to make forked lightning bolts. However, the cheap quality effect works sufficiently well for the cards.



Ice was another type I fretted over for a long time before finding out the exact same method I used for Psychic would work very well for it, too.



In all honesty, there is very little difference between its colours and those of the Flying type, but the texture effects are sufficient that nobody would confuse them.



Ghost has the darkest purple colour, though it still deserves a texture to set it apart. Quite menacing, isn't it? The spiral is again a mathematical function using distance and direction towards centre - when these two are added just right, the rungs line up and create the arms of a spiral. The function breaks down near the very centre - since the blurry gradient would be larger than the distance between spiral arms - so the function fades out to hide this. The only problem is that the nice texture is often overshadowed in the final card art.




The fairy type has as texture a variation of the flame texture from fire. It looks quite different, as the primary colour - pink - is brighter than the secondary colour - teal - while it was opposite withe fire. Some extra work is done to make the gradient interpolate hue directly, creating a mini-rainbow from pink to teal. Adorable and fierce at the same time.




Steel has a brownish grey as primary colour and blueish grey as secondary colour. On top of this, there is a sheen-like texture created by highly distorted Perlin noise, taking x+y as one coordinate and (x-y)/50 as the other. So really, it is just perlin noise rotated and skewed.


Finally, the dark type has quite a dark coloration. The primary colour is almost black, but the secondary is actually a reddish brown. This is applied by Perlin noise whose distance from the mean is squared. The final effect is a nice smoky texture, though it plays better in itself than on the card, where it is overshadowed by all the bright elements.


Since the textures are generated procedurally using a single function call, I can also use them to generate other parts of the game board, like the game board and the Idol.


If you are curious how it all looks put together, this is an example of a game in motion.


This showcases me piloting my Combo Grass deck (grow big pokémon that can attack immediately in the hand) losing against a steel/psychic deck named Jink. Apparently it's really bad to let Mawile live for several turns.

The code for all of this can be found here. For more about PokeHearth, well... I've written a lot about it and not much of it has been written particularly well. But if you are curious, this description of a procedurally generated metagame might be interesting, or perhaps just a bit about how the cards even work. Who knows.

Comments

  1. Can I use some of these as the type textures on a custom Pokemon card template I'm making? I'll be sure to credit you, ofc.

    ReplyDelete

Post a Comment