Setting and getting an accurate FPS?

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
vine
Prole
Posts: 5
Joined: Sun Dec 02, 2012 4:59 pm

Setting and getting an accurate FPS?

Post by vine »

I found some code on the Love2D wiki for locking the FPS of my game to a specified amount at https://love2d.org/wiki/love.timer.sleep.
Visibly it seems to be working (in my project), but love.timer.getFPS() is reporting numbers other than what I set the FPS to.
Attached is a .love file that shows the issue in the simplest form; FPS is set to 30 but is displaying as 59~.

In my actual project file I've seen it report anything from 23 to 112 using the same code from the wiki.
Can anyone enlighten me on what the problem is?
Attachments
FPS.love
(384 Bytes) Downloaded 134 times
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Setting and getting an accurate FPS?

Post by Boolsheet »

Hm, I thought there already was a thread about that exact problem, but I can't find it. Perhaps it was discussed in IRC.

There's an issue with that example function. In LÖVE, the dt passed to love.update is the time that passed from the last.update call to the current. The idea to just sleep the remaining time is valid, but the chosen place to sleep is wrong. Sleeping in love.update will increase the dt of the current frame and it will sleep less in the next update because of it. That's where the doubled frame rate comes from.

love.update is not the best place to do the frame limiting. A better solution would be to sleep right after love.graphics.present. We could just hook the function, but it's cleaner if we modify love.run for that. You'll see that the main loop includes several things that are executed in a certain order. First is the event handling, then love.timer.step updates dt and the fps counter, then the calls to love.update and love.draw, and finally the buffer swap with love.graphics.present. The love.timer.sleep call there is a very simple limiter that prevents LÖVE from consuming all the CPU cycles unnecessarily. You can remove it if you deploy your own limiter.

We can now put something simple behind love.graphics.present to get some kind of frame rate limit.

Code: Select all

function love.run()
    local fps = 30

    math.randomseed(os.time())
    math.random() math.random()
    if love.load then love.load(arg) end
    local dt = 0
    while true do
   
        local frame_start_time = love.timer.getMicroTime() -- Takes a time measurement for the start time of the frame.

        -- Rest of the love.run code.

        if love.graphics then love.graphics.present() end

        local frame_end_time = love.timer.getMicroTime() -- Takes a time measurement for the stop time of the frame.
        local frame_time = frame_end_time - frame_start_time -- The time it took for this frame to be completed.
        if frame_time < 1 / fps then
            love.timer.sleep(1/ fps - frame_time)
        end

    end
end
This is just an approximation. If we're lucky, love.timer.sleep provides millisecond precision, but that can vary. You can't really get 100% accurate as the workload constantly changes. You can busy wait the remaining millisecond to get even closer, but some may consider that wasting CPU cycles. :P
Shallow indentations.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 3 guests