Stuttering & Fixed Timesteps

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.
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Stuttering & Fixed Timesteps

Post by Taehl »

Because if I clamp dt, then things will start running in slow motion when the framerate drops too low. Doing it the way I did ensures that they always go at the right speed, no matter what the framerate is.
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
User avatar
Kadoba
Party member
Posts: 399
Joined: Mon Jan 10, 2011 8:25 am
Location: Oklahoma

Re: Stuttering & Fixed Timesteps

Post by Kadoba »

Bryant wrote: How does this run on your machines? Jittery? Smooth?
Sorry but it's still pretty jittery for me.

I do the fixed timestamp thing in my projects with pretty good results. I normally don't redefine love.run and just go off the value that is passed to love.update I'm not sure how helpful it will be but I made an example love showing off my approach. I heavily commented it so it should be easy to follow.
Attachments
Timestep.love
(13.58 KiB) Downloaded 258 times
User avatar
yared0319
Prole
Posts: 4
Joined: Thu Jan 19, 2012 2:44 am

Re: Stuttering & Fixed Timesteps

Post by yared0319 »

I had the same stuttering issue when turning v-sync on. This thread (first among others) was extremely helpful to me in coming up with a solid "fixed timestep" loop that solved my issue.

As thanks, here's some easily reusable code that should do exactly what's needed for the next person that has this issue. The length of the update timestep depends on how much time you think it takes your update function to work. I have it set to 1/1000 of a second for my game/demo and it's very smooth now, even with v-sync on.

Code: Select all

function love.setUpdateTimestep(ts)
  love.updateTimestep = ts
end

function love.run()

  math.randomseed( os.time() )
  math.random() math.random()
  
  if love.load then love.load(arg) end
  
  local dt = 0
  local accumulator = 0
  
  -- Main loop
  while true do
  
    -- Process events.
    if love.event then
      love.event.pump()
      for e,a,b,c,d in love.event.poll() do
        if e == "quit" then
          if not love.quit or not love.quit() then
            if love.audio then love.audio.stop() end
            return
          end
        end
        love.handlers[e](a,b,c,d)
      end
    end
        
    -- Update dt for any uses during this timestep of love.timer.getDelta
    if love.timer then 
      love.timer.step()
      dt = love.timer.getDelta()
    end

    local fixedTimestep = love.updateTimestep
    
    if fixedTimestep then       
      -- see http://gafferongames.com/game-physics/fix-your-timestep  
      
      if dt > 0.25 then      
        dt = 0.25 -- note: max frame time to avoid spiral of death
      end     
      
      accumulator = accumulator + dt
      --_logger:debug("love.run - acc=%f fts=%f", accumulator, fixedTimestep) 

      while accumulator >= fixedTimestep do
        if love.update then love.update(fixedTimestep) end
        accumulator = accumulator - fixedTimestep
      end
      
    else
      -- no fixed timestep in place, so just update
      -- will pass 0 if love.timer is disabled
      if love.update then love.update(dt) end 
    end
    
    -- draw
    if love.graphics then
      love.graphics.clear()
      if love.draw then love.draw() end
      if love.timer then love.timer.sleep(0.001) end
      love.graphics.present()
    end
      
  end
  
end
User avatar
eduwhan
Prole
Posts: 3
Joined: Sun Jan 11, 2015 10:21 pm

Re: Stuttering & Fixed Timesteps

Post by eduwhan »

Hi. This is my first post. I was struggling with my framerate and stuttering and found this thread and it helped me alot. I've incorporated the interpolation and have also included an example so you can see it in action.

This is an excerpt from main.lua:

Code: Select all

ship = {  x=315,  y=526,
          prev_x=315,  prev_y=526,
          view_x=315,  view_y=526  }

function love.setUpdateTimestep(ts)
  love.updateTimestep = ts
end

function love.run()

  math.randomseed( os.time() )
  math.random() math.random()
  
  if love.load then love.load(arg) end
  
  local dt = 0
  local accumulator = 0
  
  -- Main loop
  while true do
  
    -- Process events.
    if love.event then
      love.event.pump()
      for e,a,b,c,d in love.event.poll() do
        if e == "quit" then
          if not love.quit or not love.quit() then
            if love.audio then love.audio.stop() end
            return
          end
        end
        love.handlers[e](a,b,c,d)
      end
    end
        
    -- Update dt for any uses during this timestep of love.timer.getDelta
    if love.timer then 
      love.timer.step()
      dt = love.timer.getDelta()
    end

    local fixedTimestep = love.updateTimestep
    
    if fixedTimestep then       
      -- see http://gafferongames.com/game-physics/fix-your-timestep  
      
      if dt > 0.25 then      
        dt = 0.25 -- note: max frame time to avoid spiral of death
      end     
      
      accumulator = accumulator + dt
      --_logger:debug("love.run - acc=%f fts=%f", accumulator, fixedTimestep) 

      while accumulator >= fixedTimestep do
        if love.update then love.update(fixedTimestep) end
        accumulator = accumulator - fixedTimestep
      end
      
    else
      -- no fixed timestep in place, so just update
      -- will pass 0 if love.timer is disabled
      if love.update then love.update(dt) end 
    end
      
     local alpha = accumulator/fixedTimestep
      
      ship.view_x = ship.x * alpha + ship.prev_x * (1 - alpha)
      ship.view_y = ship.y * alpha + ship.prev_y * (1 - alpha)
     
    -- draw
    if love.graphics then
      love.graphics.clear()
      if love.draw then love.draw() end
      if love.timer then love.timer.sleep(0.001) end
      love.graphics.present()
    end
      
  end
  
end
I hope this will be of help to some.
Attachments
stutterfreeInterpolation.love
(5.29 KiB) Downloaded 189 times
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: Stuttering & Fixed Timesteps

Post by Przemator »

That's an old topic, but I found here some questions that I also have. I want to write a networking game with box2d, and if you don't fix the timestamp in box2d, it creates a stuttering effect.
slime wrote: Fri Sep 30, 2011 1:58 am A more optimal solution would be to separate rendering from updating entirely by putting everything except rendering into its own thread, but that's another topic. :P
Yes, that's what I was thinking! But how to do it? Can I have a constantly running update thread that would read the input instantly, update the world by a fixed dt (say 0.01 s) and then sleep until it's time for the next update? The problem is, if you want to have vsync on, then as soon as you draw, you lose control over the main thread until the next screen flip.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Stuttering & Fixed Timesteps

Post by zorg »

Triple-necroposting aside, yes, it's possible to hoist out almost everything into a separate thread (except love.event.pump, which you need to call from the main thread, and love.graphics and love.window stuff), so all your logic code could happen on not the graphics thread...

The issue is still that the graphics thread should not be on the main thread, and you can't do anything about that currently... maybe with some very deep magicks, but idk about that.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
KayleMaster
Party member
Posts: 234
Joined: Mon Aug 29, 2016 8:51 am

Re: Stuttering & Fixed Timesteps

Post by KayleMaster »

Why not leave graphics on the main thread and do your logic on a separate 'pseudo-main' thread. GUI will be a bit tricky, but it could work.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Stuttering & Fixed Timesteps

Post by zorg »

KayleMaster wrote: Fri May 11, 2018 8:35 am Why not leave graphics on the main thread and do your logic on a separate 'pseudo-main' thread. GUI will be a bit tricky, but it could work.
Windows can mess with the main thread, hence you can't be sure it isn't the culprit for the mini-stutters i've been seeing in basically -all- löve2d projects i ran on my computer; it literally can't do games like Ori and the Blind Forest or Dust An Elysian Tail not because they'd be too complex, but because this framework will never be able to produce that kind of visual smoothness and regularity with the frame times.

please prove me wrong with an example, i'd be also happier to know that i was wrong.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
KayleMaster
Party member
Posts: 234
Joined: Mon Aug 29, 2016 8:51 am

Re: Stuttering & Fixed Timesteps

Post by KayleMaster »

Yeah, probably because you're sleeping the thread and then it's up to windows to wake it up on time, which is uncommon.
If you want to hit a solid frame rate by locking up your main CPU thread, you will need to spinlock (don't put the thread to sleep; instead just spin inside the loop until enough time has passed).
The drawback is that the process may show up as using 100% of the core, which may be alarming to some people.
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Stuttering & Fixed Timesteps

Post by raidho36 »

It doesn't just show up as using 100%, it actually does uses up 100% of the CPU. It's not so much alarming as it is annoying due to unnecessary fan spin and battery drain.
Post Reply

Who is online

Users browsing this forum: Amazon [Bot] and 53 guests