1
\$\begingroup\$

I am aware this question has been asked before, but unfortunately I am new to the language, so the complicated explanations I've found do not help me in the least.

I need a lighting engine for my game, and I've tried some procedural lighting systems. This method works the best:

if (light[xx - 1, yy] > light[xx, yy]) light[xx, yy] = light[xx - 1, yy] - lightPass;
if (light[xx, yy - 1] > light[xx, yy]) light[xx, yy] = light[xx, yy - 1] - lightPass;
if (light[xx + 1, yy] > light[xx, yy]) light[xx, yy] = light[xx + 1, yy] - lightPass;
if (light[xx, yy + 1] > light[xx, yy]) light[xx, yy] = light[xx, yy + 1] - lightPass;

(Subtracts adjacent values by 'lightPass' variable if they are more bright) (It's in a for() loop)

This is all fine and dandy except for:

The system favors whatever comes first in the for() loop

This is what the above code looks like applied to my game: Light

On the left side you can see some weirdness going on: Problem

The loop goes top to down then to the right column: Problem

This is how the for() loop goes: for loop

Light provided from my mouse, should be a full light, but is only half: enter image description here

If I could get some help on creating a new procedural or otherwise lighting system I would really appreciate it!

\$\endgroup\$
1
\$\begingroup\$

Since your question is kind of broad, I'm going to give a kind of broad answer.

A recursive algorithm is a typical way to approach this. The algorithm "flows" outward until there's no more light to spread. Remember to put in a base case for your algorithm, or you'll never stop lighting. For example, if the next tile being selected is as bright or brighter than the current tile. Since you're likely to have large grids, you'll probably want to implement a list for your recursion instead of using the stack (it'll probably overflow). An example of this might be:

(note this is using the stack based approach, only recommended for shallow recursion, there's an example that's similar to the list approach below)

Light(x, y, value)
  (x,y).lightvalue = value
  if(value-1 > 0)
      if((x-1, y).lightvalue < value-1)
          Light(x-1,y,value-1)
      if((x+1, y).lightvalue < value-1)
          Light(x+1,y,value-1)
      if((x, y-1).lightvalue < value-1)
          Light(x,y-1,value-1)
      if((x, y+1).lightvalue < value-1)
          Light(x,y+1,value-1)

Clearly your case would be a lot more complex, since you want to account for sky light shining down, you'll have to keep track of if the tile has sky directly above it.

Another option is some kind of cellular automata. So each tile knows its state and can tell neighboring tiles they should update their state. Something like:

foreach(tile in tilesToUpdate)
   if(tileToLeft.lightValue > thisLightValue + 1)
       this.lightValue = tileToLeft.lightValue - 1
   else if(tileToLeft.lightValue < thisLightValue)
      tilesToUpdate.add(tileToLeft)
   //repeat for other directions

Again, this would need to be modified to allow for your sky light requirement. You'd kick off this algorithm by setting the light value of one tiles and adding it to the list of tiles to update.

You might also find it's more optimal to update all the lighting using your existing method, while making a list of tiles that will likely need to be updated by one of the above methods. These are just very simple examples that would need to be significantly optimized for your use cases, but they're a start.

You can see a related question here where I went into a bit more detail about some aspects of lighting. And another related question that might be useful.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I figured it out! All I had to do was have 4 separate passes in different directions. Thanks, though! \$\endgroup\$ – ben Oct 25 '13 at 17:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.