2D Tile Lighting

Cyral picture Cyral · Mar 26, 2012 · Viewed 7.9k times · Source

I'm adding lighting to my XNA 2D tile based game.

I found this article useful, but the way its done it does not support collision. What I'd like is a method to do the following

  • Have always lit point
  • Collision (If the light ray hits a block, then dim the next block by whatever amount until its dark to simulate shadows)

I've been searching around for quite a while but no luck (I did find Catalin's tutorial, but it seemed a bit advanced for me, and didn't apply to tiles well due to redrawing the entire game for each point)

Answer

Cyral picture Cyral · Jun 6, 2013

I'll share my method for applying a smooth lighting effect to a 2D tile grid. ClassicThunder's answer provides a nice link for shadows.

First off, we will need to calculate the lighting values of each tile which will be blurred later. Let me illustrate how this works before I get into the code.

Lighting

Basicly what we do is loop through all the tiles, starting from the top, if a tile is blank, set the CurrentLight variable to max brightness, if we find a solid tile, set it as the CurrentLight variable and subtract an "absorbsion" amount from the CurrentLight. This way, on our next solid tile, when we set the tile to the CurrentLight value, it will be slightly less. This process is repeated until the array is iterated.

Now there will be a nice top to bottom lighting effect, but it isn't that great. We must repeat this process 3 more times, for bottom to top, left to right, and right to left. And it can be repeated more times for better quality.

Basically running this code on every tile in the loop

if (tile.Light > CurrentLight) //If this tile is brighter than the last, set the current light to the tiles light
    CurrentLightR = tile.Light;
else if (CurrentLight != 0f) //If it is less, and isnt dark, then set the tile to the current light
    tile.Light = CurLightR;
if (tile.Light == CurLightR) //If it is the same, subtract absorb values
    CurrentLight -= tile.Absorb;

And there you go, nice tile lighting. However if you want a less "pixelized" look, you can check out my question on gamedev for that.