Okay, I need something visual and pretty to happen in the game as I’ve been staring at the same boring assets for too long. Even animations are now just a bunch of numbers. So let’s add lights the game! This is something that (can) add a great deal to the atmosphere and just improve the general feel of it. I think I will do simple per-tile illumination. A light can exist “over” any tile and it will light the tiles around it. I won’t do any “real” lights or shader stuff. I looked at various solutions for this, but I don’t think I want to refactor a lot of how my world objects work just to enable lights that will likely not even work out right.
Anyway, I can easily implement a light value for a tile, have the world object tint the sprite (with my shader that can darken it), and then set it to some value (purely random here):
I will be adding light generation with the dungeon generator. For now, I am just placing a light in every room in the middle of it. With an approximate light reduction, this looks like this:
I am, of course, implementing some actual light decay logic, so that I can know how much light reaches each tile:
This also means I can overlap the lights and they correctly decided which light “wins” (not doing double-light for now, although it’s a matter of some math):
Now, I don’t want light to be randomly placed. In fact, I want each room to specify how it places the lights. For that, I am adding a light selection/designation for each of my room’s tiles and an editor to do so:
Thus I can get the light in any spot I want, which is especially useful for testing:
Thus the lights I spawn are designed to go there:
Of course, my wall don’t stop lights:
In fact, the lights don’t care about tiles, they will illuminate through walls and void.
So lights need line of sight. This is very similar to my line of sight for mobs, but I am implementing an even simpler mechanics. I don’t care about all the restrictions and props and whatnot. First, I gather the tiles furthest away from the light:
This is essentially a border that gives me an area to work in:
Then I calculate a line to every tile on the border. This ensures that every single tile will be visited (at least once):
So I get a nice list of ordered lines:
And with that I can apply the illumination dropoff again and it works out nicely:
Now I can easily “stop the line” whenever it hits an obstacle, such as a wall:
Any tiles deemed to be unilluminatable will not receive a light value and stay dark. Since my tiles have different styles (wall top/side, door open/closed), I am also adding an additional value to every tile which describes how “lightable” it is. There can be a fully lightable tile — passes light through. Partly lightable tile that gets lit but does not let the light through. And unlightable tile, which never gets lit. And all this works out nicely with stuff like wall sides and doors:
Of course, if I walk through, the lights don’t update, because I never actually “rebake” any of my lights:
So that’s the final feature:
All of this is relatively slow performance-wise. But I’m “baking” it–checking lights once and caching the light values–so I don’t care much if it’s slow. Besides, I wrote the algorithm with pure math, so it’s not like expensive Unity scene lights.
Now I have to go through every room and add lights…
Well, this isn’t that pretty, but it’s functional. I still need to solve a bunch of issues and technicalities. I also want dynamic lights for stuff like explosions, and not just the static ones. I will also think on how I can improve the actual per-tile effects, but at least I have consistent data and pipeline now. I might consider some sort of vertex shader for my quads, but it all sounds very complicated and time-consuming. We’ll see. Or may be I’ll just work on something else.