light_world.lua ignoring setVisible()

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
soulmata
Prole
Posts: 31
Joined: Sat Jan 26, 2013 8:14 am
Contact:

light_world.lua ignoring setVisible()

Post by soulmata »

I have been using light_world for a while now, though to date I've been using it with statically-placed lights that do not move. Lately I am discovering a really odd behavior when I want to selectively decide if a light is visible or not.

The logic is rather simple:
1) in love.draw, set all lights to not visible ( setVisible(false) )
2) for each tile to render, see if that tile contains a light. if it does, update its relative position and make it visible

This does not work at all. As soon as the light has been made invisible, it will never appear again. Dumping the contents of the object, you can clearly see the light SHOULD be appearing. It'll look something like this:

Code: Select all

        (*)     l       |
        z       =>      1
        visible =>      true
        red     =>      1
        green   =>      1
        blue    =>      1
        glowStrength    =>      0
        glowSize        =>      0.1
        x       =>      1013
        y       =>      631
        angle   =>      6.2831853071796
        direction       =>      0
        range   =>      110
        smooth  =>      1
        is_on_screen    =>      true
I can immediately invoke update() on the light world or not, it doesn't make a difference. What DOES work is if I completely destroy the light object and then immediately re-create but, but this is so slow as to be totally unusable. I have no idea why the library is behaving in this way, and it seems to have not been updated in a long time, so I guess this is a long shot, but I'm hoping someone here might be able to help.

Here's a bit of code that determines if a light is going to be drawn or not:

Code: Select all

          if (maps[room][layer][roomx][roomy].fn) then -- tile has a light
            if (global.state.screen.light) then
              local lsdx = rangeXmax - mx + 1 -- tracking which portion of the map is going to be drawn
              local lsdy = rangeYmax - my + 1
              if not(lights) then lights = { } end
              local id = room .. maps[room][layer][roomx][roomy].uid --creating a unique identifier for the light
              if not(lights[id]) then -- need to re-create this light
                print("creating light in room " .. room .. " at position " .. lsdx .. " " .. lsdy .. " " .. ((spreadX*64)+offsetX-64) .. " " .. ((spreadY*64)+offsetY-64))
                local ld = f_ed_get_light(lightsdata[maps[room][layer][roomx][roomy].fn].fn) -- describe the light
                local offset_x, offset_y = 0, 0
                if ld[7] then offset_x = offset_x + ld[7] end
                if ld[8] then offset_y = offset_y + ld[8] end 
                lights[id] = light:newLight(((spreadX*64)+offsetX-64) + offset_x, ((spreadY*64)+offsetY-64) + offset_y, ld[1], ld[2], ld[3], ld[4])
                if ld[5] then lights[id]:setAngle(ld[5]) end
                if ld[6] then lights[id]:setDirection(ld[6]) end
              else -- light was already made, update position
                --print("updating light " .. id .. " in room " .. room .. " at position " .. lsdx .. " " .. lsdy)
                local ld = f_ed_get_light(lightsdata[maps[room][layer][roomx][roomy].fn].fn)
                local offset_x, offset_y = 0, 0
                if ld[7] then offset_x = offset_x + ld[7] end
                if ld[8] then offset_y = offset_y + ld[8] end
                lights[id]:setVisible(true)
                lights[id]:setPosition(((spreadX*64)+offsetX-64) + offset_x, ((spreadY*64)+offsetY-64) + offset_y)
              end


If I simply run that code as-is, the lights work, but as soon as you move, many other lights will start to be be created and will never get cleaned up. I tried many, many, many methods to clean them up, and none short of destroying the light worked. Using this method below causes all the lights to go invisible and never return, no matter how many times you make them visible again afterward:

Code: Select all

        if (global.state.screen.light) then
          for k,v in pairs(lights) do
            if (lights[k]) then
              lights[k]:setVisible(false)
            end
          end
        end
Endless Dark: An existential horror game written in LOVE in which you are tasked with keeping a sleeper colony ship intact.
User avatar
soulmata
Prole
Posts: 31
Joined: Sat Jan 26, 2013 8:14 am
Contact:

Re: light_world.lua ignoring setVisible()

Post by soulmata »

I was able to resolve this, in what I consider a combination of a decent and outright stupid way. The video result is below.

Basically, the library is heavily bugged, as far as I can tell, and many of the methods just outright do nothing (particularly, the screen size refresh and the setVisible methods). Additionally, I found it unreliable in destroying individual lights, throwing an exception if a light was destroyed that had already fallen off screen (but was still active). I managed to make it work in a decent manner by doing the following:

1) For the viewable area, scan a region outside of that of N pixels for additional lights, up to the maximum size of lights used

2) Draw that light and offset it appropriately, but tell light_world that your viewable area is in fact quite a bit larger, so you can get light cast on tiles that should be illuminated, but their light source is currently off screen

3) Set an "alive" flag on the light every frame if the overscan would find it. When a light falls too far out of range, that flag isn't updated. At that point, the remove() function is wrapped in a protected call and blindly fires against that light until it is actually removed

This resolved all the crashing, got the lights to move and display properly, kept the framerate decent and made the scenes look good enough. You can see below that "ACTIVE LIGHTS" fluctuates as I move from room to room, and more telling, Drawcalls also fluctuates with it, indicating the lights are getting cleaned up properly.


edit: apparently I am not allowed to embed youtube videos or something

https://www.youtube.com/watch?v=0FPzEFnc1tU
Endless Dark: An existential horror game written in LOVE in which you are tasked with keeping a sleeper colony ship intact.
User avatar
togFox
Party member
Posts: 764
Joined: Sat Jan 30, 2021 9:46 am
Location: Brisbane, Oztralia

Re: light_world.lua ignoring setVisible()

Post by togFox »

There are many forks of the source code - perhaps someone has improved the library.

Just last night I tried and failed to use Luven because it's also bugged.

I need simple lighting so I'll try light_world knowing it might not be perfect.
Current project:
https://togfox.itch.io/backyard-gridiron-manager
American football manager/sim game - build and manage a roster and win season after season
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: light_world.lua ignoring setVisible()

Post by pgimeno »

Löve is awesome, but it has a *huge* problem. Each new major version completely breaks compatibility with older versions. As a consequence, libraries break, and since library authors rarely stay around for long enough as to update their libraries to a newer version, that causes the libraries to become rotten.

It's almost as if we have to start all over again from nothing with each new version.
User avatar
slime
Solid Snayke
Posts: 3129
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: light_world.lua ignoring setVisible()

Post by slime »

pgimeno wrote: Sat Dec 03, 2022 3:08 pm Löve is awesome, but it has a *huge* problem. Each new major version completely breaks compatibility with older versions. As a consequence, libraries break, and since library authors rarely stay around for long enough as to update their libraries to a newer version, that causes the libraries to become rotten.

It's almost as if we have to start all over again from nothing with each new version.
I don't think it's that dramatic. love 11 only had a single major breaking change (close to 99% of code written for love 0.10 works with love 11), and that happened almost 5 years(!) ago. The light_world library has been updated long after love 11's release. Luven started development well after love 11 was released. It sounds like the problems with the library are largely the library's fault or in user code.
User avatar
togFox
Party member
Posts: 764
Joined: Sat Jan 30, 2021 9:46 am
Location: Brisbane, Oztralia

Re: light_world.lua ignoring setVisible()

Post by togFox »

To be clear - Luven is indeed a Luven problem and I've logged a github issues against Luven.

Generally speaking, the most common issue I have with libraries is no/poor documentation.
Current project:
https://togfox.itch.io/backyard-gridiron-manager
American football manager/sim game - build and manage a roster and win season after season
Post Reply

Who is online

Users browsing this forum: No registered users and 21 guests