6
\$\begingroup\$

I am working on a top-down, 2d cell-based RPG game. I would like to implement a cell based lighting system, something like this and this.

I basically have several light sources and light deteriorates on every cell in every direction. Something like the below (numbers represent the level of light in each cell):

1 1 1 1 1 0 0 0 0 0 0
1 2 2 2 1 0 0 1 1 1 0
1 2 3 2 1 0 0 1 2 1 0
1 2 2 2 1 0 0 1 1 1 0
1 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 1 2 1 0 0 0 0
0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0

So basically I insert a source of light of "strength" x at a given spot. I then set the surrounding cells' light strength to x-1 and so on until I reach zero (or a set global minimum value). I am looking for an efficient algorithm to implement and generate such a lightning grid based on my light sources and any tips regarding such implementation.

I am currently not looking into field of view algorithms, just an efficient way of generating the above. Any help will be much appreciated.

EDIT: Just to clarify, this should handle movement of light sources (e.g. player walking with a torch).

EDIT2: Ok, I've solved my problem myself based on the simple distance suggestion by Jari (thus I'll accept his answer although I'm still looking for a more efficient way of generating such array). If anyone's interested here is a demo of what I came up with (multiple light sources with alpha compositing)

\$\endgroup\$
4
\$\begingroup\$

I'd probably just create a 256x256 (or some such) pre-calculated array and scaled that as needed; that way you can do all sorts of special lights if you want as well.

Going procedurally, the easiest way would probably be to just calculate the distance.

xd = posx-centerx
yd = posy-centery
dist = sqrt(xd*xd+yd*yd)
pow = maxpow - dist
if (pow < 0) pow = 0

and then just draw a (maxpow*2)-1 square around the light center..

Something like that. Doesn't give exactly the results you mentioned, because this one generates a more round light (yours are rather square).

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Well a round light is good (as seen here). Your algorithm works well but only for one light source, any suggestions for handling multiple light sources? Let's say I have a list of light sources, should I, for each cell, calculate the distance from those light sources and sum up illumination - is that efficient? How should I add up illumination? \$\endgroup\$
    – MMM
    Feb 6 '12 at 11:21
  • \$\begingroup\$ Just a thought, should it be max(distance_a, distance_b, ...)? \$\endgroup\$
    – MMM
    Feb 6 '12 at 11:26
  • 1
    \$\begingroup\$ I said, "just draw a (maxpow*2)-1 square around the light center" - do this for each light source, adding them together, capping (with max function) to some sane maximum value. \$\endgroup\$ Feb 6 '12 at 12:33
  • 1
    \$\begingroup\$ What do you mean by drawing a square? All I need is this lightning array, I can take it from there. \$\endgroup\$
    – MMM
    Feb 6 '12 at 12:49
  • 1
    \$\begingroup\$ Ok I've created a prototype using your simple distance suggestion and my max() approach and it seems to work fine, I'm just wondering if there's a more efficient way of doing it. Here's a jsFiddle with the prototype. \$\endgroup\$
    – MMM
    Feb 6 '12 at 13:13
0
\$\begingroup\$

You could treat the light as a fluid that flows outwards from the light source and is blocked by certain blocks. You could then model this using cellular automata

\$\endgroup\$
1
  • \$\begingroup\$ Thanks but as I've said I'm not looking for a point of view solution, so I don't need to treat the light as fluid and block it using blocks, plus I can use libraries like libfov. \$\endgroup\$
    – MMM
    Feb 6 '12 at 12:08

You must log in to answer this question.

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