Page 3 of 4

Re: Stuttering & Fixed Timesteps

Posted: Tue Oct 04, 2011 1:00 pm
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.

Re: Stuttering & Fixed Timesteps

Posted: Tue Oct 04, 2011 3:35 pm
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.

Re: Stuttering & Fixed Timesteps

Posted: Sat Mar 30, 2013 7:13 am
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

Re: Stuttering & Fixed Timesteps

Posted: Sun Jan 11, 2015 10:42 pm
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.

Re: Stuttering & Fixed Timesteps

Posted: Sun Apr 15, 2018 5:39 pm
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.

Re: Stuttering & Fixed Timesteps

Posted: Fri May 11, 2018 7:33 am
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.

Re: Stuttering & Fixed Timesteps

Posted: Fri May 11, 2018 8:35 am
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.

Re: Stuttering & Fixed Timesteps

Posted: Fri May 11, 2018 4:35 pm
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.

Re: Stuttering & Fixed Timesteps

Posted: Fri May 11, 2018 7:07 pm
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.

Re: Stuttering & Fixed Timesteps

Posted: Fri May 11, 2018 9:48 pm
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.