enterFrame listener performance problem...

I have a GameLoop function which is called by the “enterFrame” event.

Now I thought to keep things simple I will run the code, like this:

local check=false GameLoop = function (event)     if check==false then        check=true        -- CODE HERE        check=false     end end

I thought with the check variable I can make sure my graphics collision detection (code in the CODE HERE part… circle circle col detection) is checked only once and not too often with each call of the GameLoop function.

Everything works perfectly on the Simulator and fast test devices… but now I have a slow test device (and also showing banner ads on top of the screen) and the GameLoop is called many times BEFORE the – CODE HERE part has finished running.

What can I do to get better performance for this?

Sometimes the function get stuck and the check=true will NOT change to check=false at all btw.

How are you doing this kind of performance hungry function calls?

How is your collision detection set up? Generally collision detection is a listener that you don’t have to call manually,  it will run whenever a collision happens.

I’m not using physics for the collision check… just a traditional circle circle collision check if objects are near to each other.

But the slow down happens already with only about 4 objects on screen which should not make any problems.

post your collision check code because it shouldn’t slow anything down - unless you are doing complicated maths. box collisions would be faster as the maths is more simple.

the other thing you can do is check every 5 or 10 game cycles for collisions - depending on the speed of your objects.  taking this a step further you could check the current fps and adapt accordingly.  if your game is running 30 fps then check often, if it drops to 20 fps then check less often.

Can you post your full code? If not, can you post a boiled down version? - Reduce the problem to it’s primary failing parts.

Corona is single-threaded, so once you’e in ‘GameLoop’, it can’t be interrupted.  Something else must be going on here.

I’d like to ask for a simplified example demonstrating this.  i.e. A complete (main.lua, config.lua, …) working example that we can download and try ourselves.  

I’m sure if you supply that, one of us can resolve the issue you’re encountering.

Thank you for all your feedback! It isn’t easy to show the code, because I’m working with a lot of modules which get accessed from inside the GameLoop. But with all the info you gave me I can look into this and try to find the exact part which is causing the issue. Then I will get back here.

Thx again!

Drop this into a module somewhere.  Call startTimer() at the start and then place a few stopTimer() calls at random places in your code and it will print the execution time in ms.  It is a real simple way to time blocks of code.

I’ve found this real helpful in finding slow code blocks.

local startTime = nil function startTimer()   startTime = system.getTimer() end function stopTimer()   local elapsedTime = system.getTimer() - startTime   print("Time = "..elapsedTime.." ms") end

Thank you very much for your help and the code!

local check=false GameLoop = function (event)     if check==false then        check=true        -- CODE HERE        check=false     else -- ENTERED AREA check=false else end

Here is a part of the code from the – CODE HERE area above:

for x=#Weapons,1,-1 do     if Weapons[x].active==true and Weapons[x].isVisible==true and Weapons[x].lockedOnEnemy and Weapons[x].shootingAllowed==true and \_G.paused==0 then         if not Weapons[x].freqTimer then             -- we only shoot if we are not still rotating this weapon:             -- allow shooting if we have the rotation of the weapon finished:             if not Weapons[x].transTo then                 shootAtEnemy (Weapons[x]) -- shooting as long in given Frequency as it is in range             else                 -- here we are if we have a rotation towards an enemy                 -- we check if the current aimed at enemy is visible and in case not we set back the target for this weapon                 if Weapons[x].lockedOnEnemy and Weapons[x].lockedOnEnemy.isVisible==false then                     Weapons[x].lockedOnEnemy=nil                 end             end         end     end      end

It is the shootAtEnemy function which on a slow device is making the GameLoop enter the ENTERED AREA (see code above!). In the simulator or a fast device the ENTERED AREA is not getting entered at all.

The shootAtEnemy function is first checking if the weapon is still active before creating bullets, moving the bullets towards enemies and doing collision checks for the bullets with the enemy or other enemies.

Is there a way to running the GameLoop on the slow device using shootAtEnemy without entering the ENTERED AREA? Or how can I make sure the stuff happening in shootAtEnemy is NOT delaying the GameLoop?

As Ed said there is no way gameloop can be called whilst it is already being executed.  that would imply multi-threading and Corona is single-threaded.

In other words the first execution of gameloop will always finish before a second execution can start.

So if I get this correctly the code NEVER should be running the ENTERED AREA part from above, right?

Mhhh…

BTW: I’m showing admob banner ads on top of the screen.

Okay… I now have found the issue with the code:

On device (where an ad is shown) I’m using a global to store the height of the banner ad. In the module handling the ShootAtEnemy function I still had a local with the same name… resulting in the value not known causing a hidden runtime error in ShootAtEnemy. Because the rest of the game was running on and continued the error was not an eye catcher and I only found it after looking through all the log output for the device. At first I didn’t think of an error at all because the whole game continued playing.

Thank you all for your help!!!

I use an underscore for globals… for example _W, _H store the actual pixel width and height which I often use for dynamic UI placement.

If I accidentally declare a local W they will never clash. Some devs use G_ or other schema.  Choose one that works for you really - save a LOT of headache

this is the perfect example of why to avoid globals! (not to mention they’re also accessed via the slowest possible mechanism)

my go-to recommendation is Niklas Frykholm’s GLOBAL_Lock , then wrap it in a conditional to only run in simulator (cuz not worth crashing a production version if a global leak still makes it through testing, as maybe it’s of the “harmless” variety)

tho a caveat/gotcha is to first include composer (since it includes physics, which leaks a global “physics”) before locking.  (there are a couple other corona libs that also leak, ottomh “crypto” is one, but don’t recall them all - if you discover one just include it prior to lock)

How is your collision detection set up? Generally collision detection is a listener that you don’t have to call manually,  it will run whenever a collision happens.

I’m not using physics for the collision check… just a traditional circle circle collision check if objects are near to each other.

But the slow down happens already with only about 4 objects on screen which should not make any problems.

post your collision check code because it shouldn’t slow anything down - unless you are doing complicated maths. box collisions would be faster as the maths is more simple.

the other thing you can do is check every 5 or 10 game cycles for collisions - depending on the speed of your objects.  taking this a step further you could check the current fps and adapt accordingly.  if your game is running 30 fps then check often, if it drops to 20 fps then check less often.

Can you post your full code? If not, can you post a boiled down version? - Reduce the problem to it’s primary failing parts.

Corona is single-threaded, so once you’e in ‘GameLoop’, it can’t be interrupted.  Something else must be going on here.

I’d like to ask for a simplified example demonstrating this.  i.e. A complete (main.lua, config.lua, …) working example that we can download and try ourselves.  

I’m sure if you supply that, one of us can resolve the issue you’re encountering.

Thank you for all your feedback! It isn’t easy to show the code, because I’m working with a lot of modules which get accessed from inside the GameLoop. But with all the info you gave me I can look into this and try to find the exact part which is causing the issue. Then I will get back here.

Thx again!