timer.peformWithDelay and slowdowns

Hi community,

although I’ve already release my game (if you wanna try, please check www.squarestation.net), there’s one issue I couldn’t really find a solution for:

My game runs fine with 60fps on most phones, but with less powerful ones there’s sometimes a drop in the framerate.

My game uses the physics API together with a lot of timer.performWithDelay calls.

Now, when the framerate drops, the physical objects will simply take more time to move from a to b. On the other hand, the timer.performWithDelay is not depending on the frame rate but simply on the passed time.

This is then where things get out of sync with frame-rate-drops: on part (phyics) is using the framerate as a reference, while the other part (timer.performWithDelay) is taking the time as a reference.

I guess there are different ways to solve this problem, but the most obvious would be to tell the timer.performWithDelay to use the framerate as a reference. Can this be somehow defined?

Thanks,

Chris

Enter frame event are used to for ‘taking the frame rate’ as a reference.

Perform with delay is a time based system, both ignorant of and uninterested in frame rates.  

You must listen for the “enterFrame” event AND measure dt (delta time) if you want a system that is both time and frame sensitive.

PS - Great looking game!

Thanks for your reply and checking out the game :slight_smile:

Using enterFrame, I’d count the number of frames and translate 60 frames to 1 second. Based on this I’d then create my own performWithDelay function. Gonna try this!

You cannot rely on the time between frames to be consistent.  That is why you need to cacluate frame to frame deltas and adjust calculations based on the actual amount of time that has passed.

Ex:

At 60 FPS, ideally one frame would be 16.66 ms.  

In reality, frames will be like this:

16 ms

17 ms

16 ms

18 ms

14 ms

Thus, you need to account for this or you’ll get ‘lurching’ movements and changes if you assume each frame is always exactly 16.66 ms.

Not sure if I then understand the approach.
Afaik I could write my own performWithDelay function that uses the frames as a reference but I cannot change the physics api to use time as a reference.

But I could switch to something like performWithFrameDelay where you pass the number of frames to wait. That might then be more in sync with the timeing of the physics apis?

This code will create a timer using system time, and execute based on framerate.

local myTimers = {} local createTimer = function (timerId,delay,onInterval,interval,onComplete) local updateTime = system.getTimer() local updateInterval = 0 local myTimer myTimer = function () if system.getTimer()-updateTime \>= delay then updateTime = system.getTimer() updateInterval = updateInterval + 1 if onInterval then onInterval() end if updateInterval \>= interval then Runtime:removeEventListener("enterFrame",myTimer) if onComplete then onComplete() end end end end Runtime:addEventListener("enterFrame",myTimer) cancelTimer = function () Runtime:removeEventListener("enterFrame",myTimer) end myTimers[(timerId or #myTimers+1)] = {timer = myTimer,cancel = cancelTimer} end --createTimer("testTimer",500,helloworld,5) --myTimers["testTimer"].cancel()

Enter frame event are used to for ‘taking the frame rate’ as a reference.

Perform with delay is a time based system, both ignorant of and uninterested in frame rates.  

You must listen for the “enterFrame” event AND measure dt (delta time) if you want a system that is both time and frame sensitive.

PS - Great looking game!

Thanks for your reply and checking out the game :slight_smile:

Using enterFrame, I’d count the number of frames and translate 60 frames to 1 second. Based on this I’d then create my own performWithDelay function. Gonna try this!

You cannot rely on the time between frames to be consistent.  That is why you need to cacluate frame to frame deltas and adjust calculations based on the actual amount of time that has passed.

Ex:

At 60 FPS, ideally one frame would be 16.66 ms.  

In reality, frames will be like this:

16 ms

17 ms

16 ms

18 ms

14 ms

Thus, you need to account for this or you’ll get ‘lurching’ movements and changes if you assume each frame is always exactly 16.66 ms.

Not sure if I then understand the approach.
Afaik I could write my own performWithDelay function that uses the frames as a reference but I cannot change the physics api to use time as a reference.

But I could switch to something like performWithFrameDelay where you pass the number of frames to wait. That might then be more in sync with the timeing of the physics apis?

This code will create a timer using system time, and execute based on framerate.

local myTimers = {} local createTimer = function (timerId,delay,onInterval,interval,onComplete) local updateTime = system.getTimer() local updateInterval = 0 local myTimer myTimer = function () if system.getTimer()-updateTime \>= delay then updateTime = system.getTimer() updateInterval = updateInterval + 1 if onInterval then onInterval() end if updateInterval \>= interval then Runtime:removeEventListener("enterFrame",myTimer) if onComplete then onComplete() end end end end Runtime:addEventListener("enterFrame",myTimer) cancelTimer = function () Runtime:removeEventListener("enterFrame",myTimer) end myTimers[(timerId or #myTimers+1)] = {timer = myTimer,cancel = cancelTimer} end --createTimer("testTimer",500,helloworld,5) --myTimers["testTimer"].cancel()