0
\$\begingroup\$

I have a 2D pixel art game where characters can be covered in a flammable black oil-like substance and I am looking for a simple way to depict that visually.

Simply tinting the character black won't work since that will just make it appear more dimly lit. It needs some form of texture or something to indicate it is oil. Simply drawing over the character with a repeating oil texture will give away the trick when the character is animated because when e.g. the head moves, that part of the texture stays in place. At least, the texture would need to have no obvious identifiable point of reference the player can track. Perhaps Perlin Noise could be used to produce such an effect somehow?

Any ideas on how to make an effect like that? Are there any examples of 2D games doing something like this?

To give you an idea of resolution and art style (Blasphemous):

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ Try a Black outline? \$\endgroup\$
    – agone
    Commented Feb 4 at 23:55

1 Answer 1

4
\$\begingroup\$

I'd like to propose taking some inspiration from the 3D graphics / PBR world. From that perspective, the problem here is that your sprite image combines into a single color value, two different properties of each part of the character: its reflectance, the “actual color of the surface”, and how much light is falling on it.

So, one possible solution would be to separate those two properties. Have one image that is “flat”, un-shaded colors, and another image that has all the lighting effects — the shadows and highlights. Then, for normal rendering, you multiply the color texel by the light texel (probably multiplied by a large constant so that there's room for the lights to saturate the color to white for highlights), and for oily rendering you substitute a uniform dark gray (or perhaps a faint "oil slick" rainbow pattern) for the color. This way, the shape of the character still appears, because it still has bright highlights and shadowed parts, but the surface will appear to be oil instead of clothing and skin.


However, that requires extra work from whoever's drawing your character sprites, especially because that's not a standard 2D pixel art workflow. So if you don't want to do that, let's consider what might be a reasonable approximation instead. The key is that we want to replace the colorful materials with a dark, shiny surface. So, try these two steps:

  • Desaturate (convert to grayscale).
  • Apply a “curve” function that preserves white, but pushes all other colors much darker. By keeping the highlights, we don't lose the appearance of the character being well lit.

Doing both of those to your example sprite with simple photo editing tools gives:

Altered image

It's not perfect, but for just a little color math, it's pretty good.

I think it might be further improved by adding an effect of dripping black pixels of oil below the outline of the character — implement this like you would a drop-shadow, by sampling the sprite texture at several offset positions above the pixel being displayed and deciding whether or not to draw a scrolling drips texture based on whether any of the sprite samples are opaque.

\$\endgroup\$
5
  • \$\begingroup\$ Do you have an example of such a curve function? Which one did you use in the example? \$\endgroup\$
    – Martin
    Commented Feb 5 at 8:14
  • 1
    \$\begingroup\$ you can create a curve quite easily using math, im not sure if thats how this is done, but if you do something like color.r = r^2 that would get a nice curve. \$\endgroup\$
    – Pow
    Commented Feb 5 at 9:08
  • \$\begingroup\$ For the dripping effect I am thinking a wide texture with drops at different y-offsets that scrolls vertically and repeats horizontally. I would need a texture for each frame of animation for the drops. However, I will need to make sure a drop is not drawn partially. To prevent horizontal cut off I could have a texture that maps drop pixel to offset from its center and do draw checks using only center of drops. But what about vertical cutoff when scrolling? How can I prevent that without drawing/scrolling drops individually? Am I overthinking this? \$\endgroup\$
    – Martin
    Commented Feb 5 at 11:45
  • 1
    \$\begingroup\$ @Martin I imagined the drips would be only one pixel each (at the same scale as the sprite pixels). If you're rendering at a higher resolution than the sprite, then the trick is to make sure your offsets are always a multiple of the sprite pixel size, so that rendering stays on the grid. \$\endgroup\$
    – Kevin Reid
    Commented Feb 5 at 16:32
  • \$\begingroup\$ Hmm, about preserving white, some of my characters have white clothes, so might look a bit odd when it is so preserved, it stands out. \$\endgroup\$
    – Martin
    Commented Feb 5 at 17:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .