Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Laggy fixed time step loop  (Read 7162 times)

0 Members and 1 Guest are viewing this topic.

filipekczek7

  • Guest
Laggy fixed time step loop
« on: June 04, 2016, 06:25:48 pm »
(In the beginning, sorry for my english ;))

Hi everybody. I know that there are some similar questions about laggy fixed time step loop on SFML forum, but I didn't find answer.

Recently I remade my loop code, because previous fixed time step loop on every computer behave differently, on slower computer game was slower, on faster computer game was faster. It was something like that:
const float FPS=100.0f;
RenderWindow window;
Clock clock;
Time time;
while(window.isOpen())
{
    if(time.asSeconds()>(1.0f/FPS))
    {
        update();
        clock.restart();
       
        time=Time::Zero;
    }
    display();
    time=clock.getElapsedTime();
}

So I was searching better fixed time step loop on the internet. I found some good articles, for example:
I've decided to the last article. It's in polish language, but it doesn't matter. There is (for me) the best and the clearest loop:
float dt = 0.0f; //time since last update
float lastUpdateTime = GetCurrentTime(); //last update time
                                         //exemplary GetCurrenTime() function gets
                                         //current time from system (in SFML it's just getElapsedTime())
float accumulator = 0.0f;
const float TIME_STEP = 0.03; //time step and frame duration
                              //physics in seconds; here 30 miliseconds,
                              //about 30 updates per second
const float MAX_ACCUMULATED_TIME = 1.0; //max time gathered in single
                                        //main loop circuit
while(true)
{
    dt = GetCurrentTime() - lastUpdateTime; //calculation of the time since the last frame
    lastUpdate += dt; //substitution
    dt = std::max(0, dt); //we're making sure that dt>=0
    accumulator += dt;
    accumulator = clamp(accumulator, 0, MAX_ACCUMULATED_TIME); //we prevent
                                                                                                               //too many updates in a given loop
                                                                                                               //cycle
    GrabInput(); //<-- keyboard, mouse, network etc. events
    while(accumulator > TIME_STEP)
    {
        UpdateGame(TIME_STEP); //<-- physics and game logic update
        accumulator -= TIME_STEP;
    }
    RenderGame(); //<-- display current game state on screen
}

//clamp function
template <typename T>
T clamp(const T& what, const T& a, const T& b)
{
    return std::min(b, std::max(what, a));
}
 

In SFML implementation it looks like this:
float dt = 0.0f; //time since last update
float lastUpdateTime = 0.f;
float accumulator = 0.0f;
const float TIME_STEP = 0.03; //I initialise this variable differently: const float TIME_STEP=1.f/60.f for 60 FPS
const float MAX_ACCUMULATED_TIME = 1.0;
while(true)
{
    dt = clock.getElapsedTime().asSeconds() - lastUpdateTime; //clock is restarting in constructor
    lastUpdate += dt;
    dt = std::max(0, dt);
    accumulator += dt;
    accumulator = clamp(accumulator, 0, MAX_ACCUMULATED_TIME);
    GrabInput();
    while(accumulator > TIME_STEP)
    {
        UpdateGame(TIME_STEP);
        accumulator -= TIME_STEP;
    }
    RenderGame();
}
 

OK, this loop is working same on different computers, but now there is a new problem. My loop is lagging. It's not smooth as previous loop. It's not lagging all time, but it's noticeable. I tried to replace TIME_STEP (in UpdateGame function) to accumulator, deltaTime or lastUpdateTime, but as expected it didn't help. I tried to change timeStep and it didn't help too. I was experimenting with setFramerateLimit() and setVerticalSyncEnabled(), no changes. I think everything is calculated correctly, but to make sure I checked variables values:
...
while(accumulator > TIME_STEP)
{
    UpdateGame(TIME_STEP);

    cout << "Delta time: " << dt << endl;
    cout << "Last update time: " << lastUpdateTime << endl;
    cout << "Accumulator (before subtract): " << accumulator << endl;

    accumulator -= TIME_STEP;

    cout << "Accumulator (after subtract): " << accumulator << endl;
    cout << "Time step: " << TIME_STEP << endl;
    cout << "Max accumulated time: " << MAX_ACCUMULATED_TIME << endl;
    cout << "------------------------------------------------------" << endl;
}
...
 

Here is output (random sample):
------------------------------------------------------
Delta time: 0.0154901
Last update time: 5.5339
Accumulator (before subtract): 0.0172362
Accumulator (after subtract): 0.0005695
Time step: 0.0166667
Max accumulated time: 1
------------------------------------------------------


In deWiTTERS article in the last loop example was interpolation, which smooths everything, but I'm not sure I need it. I think there is other solution. I don't know what's wrong with this code.

Thanks for help.
« Last Edit: June 04, 2016, 06:31:38 pm by filipekczek7 »

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: Laggy fixed time step loop
« Reply #1 on: June 04, 2016, 06:46:44 pm »
I just recently had issues with my time step in another thread.  However, may what helped me will help you get a better idea of how to setup your loop:

SFML and Game time
Some pseudo code for an implementation of fixed timestep:
deltaTime = 0.1 seconds
while (windowIsOpen)
{
    currentTime = clock.currentTime
    timeToProcess = timeToProcess + currentTime - previousTime
    previousTime = currentTime

    while (timeToProcess >= deltaTime)
    {
        applyLogicAndPhysics()
        timeToProcess = timeToProcess - deltaTime
    }

    prepareDisplay()
    drawDisplay()
}

filipekczek7

  • Guest
Re: Laggy fixed time step loop
« Reply #2 on: June 04, 2016, 07:25:04 pm »
Hm... That loop is lagging too... I think it's not loop fault. I have to check more things, maybe my code is bad (I'm writing code in Code::Blocks and Visual Studio 2015, the problem is in both IDE's). Isn't your loop laggy? If yes, I think something's wrong with my code. I don't know, I have no idea.

Anyway, thanks for answer, it is another clue ;) I'll check my code (maybe tomorrow) and we'll see what next.

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: Laggy fixed time step loop
« Reply #3 on: June 04, 2016, 07:48:36 pm »
I'm using VS 2013 because I'm too lazy to upgrade.  But so far with that simple logic, objects move smoothly, but I have not tried putting a lot of objects on there to see if it makes any difference.

I thought I would throw the idea out there anyways, starting over with a small working example may help pinpoint f there is something else that could be causing any lag with the rest of your code.

Happax has a time step project that may be of interest to you since you are using C++ Kairos - Timing Library.  Since I'm using VB, and not very smart, I am unable to port it so I can use it, LOL

filipekczek7

  • Guest
Re: Laggy fixed time step loop
« Reply #4 on: June 04, 2016, 08:54:33 pm »
I use VS for a week, so I'm new to VS ;)

I've got only 3 movable objects, so it's not many.

I'm gonna make small project to see if fixed loop will work correctly.

filipekczek7

  • Guest
Re: Laggy fixed time step loop
« Reply #5 on: June 04, 2016, 10:37:04 pm »
OK... Maybe it's not professional solution, but I increased time step value. Now it's not 1/60, but 1/+200. I know, it's very unprofessional, but it's working. In most cases 30 FPS is enough, but I don't know what's wrong. I'll keep searching cause of these lags, but it's working for now. I fell bad, because it should be 30 FPS, not more than 100. Maybe it's problem with SFML, it is quite possible. I don't know.

So... My problem is "fixed" so far. But thread is still open, maybe someone has some ideas ;)
« Last Edit: June 04, 2016, 10:43:13 pm by filipekczek7 »

victorlevasseur

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: Laggy fixed time step loop
« Reply #6 on: June 04, 2016, 11:49:14 pm »
I use a fixed time update in my game and never experienced those problems.

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 878
    • View Profile
Re: Laggy fixed time step loop
« Reply #7 on: June 05, 2016, 12:33:05 pm »
Any chance you're simply not reaching the amount of iterations per second you're aiming for?

For example, if you aim at 10 ms between updates, you'd end up at 100 updates per second. But what if you only manage to actually do 90 updates per second? You'd end up accumulating more updates than you can handle at any given time, essentially causing stuttering due to the game no longer rendering (stuck in update loop).

So you should limit the number of updates you do between drawing calls/updates. If you've got more time left, just reduce the time without doing any further updating. That way your program will only keep the constant time step as long as it can and slow down in case processing takes too long to fulfill the constraints.

filipekczek7

  • Guest
Re: Laggy fixed time step loop
« Reply #8 on: June 05, 2016, 03:28:54 pm »
No no, game is not stucking in update loop (fixed time step loop), because there is accumulating limit. My limit is 1 second, but update loop is done only one time of main loop, so that's not limit fault :/

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: Laggy fixed time step loop
« Reply #9 on: June 05, 2016, 03:40:16 pm »
You said you were able to make a small example of a basic loop in another project...you might try posting that code which may help these guys better provide an explanation of what you are doing wrong, if anything  ;)

filipekczek7

  • Guest
Re: Laggy fixed time step loop
« Reply #10 on: June 05, 2016, 04:26:31 pm »
Oh, OK, but I removed this project, so I must make it again. I think I'm not doing anything wrong, but we'll see ;) I'll upload this small example later.

filipekczek7

  • Guest
Re: Laggy fixed time step loop
« Reply #11 on: June 05, 2016, 05:50:23 pm »
OK, I've got small example code, I'm using loop from this link http://temporal.pr0.pl/devblog/download/arts/fixed_step/fixed_step.pdf OK, here is the code:
#include <SFML/Graphics.hpp>
#include <algorithm> //for max() and min() functions

using namespace std;
using namespace sf;

template <typename T>
T clamp(const T& what, const T& a, const T& b)
{
        return min(b, max(what, a));
}

int main()
{
        //setting window
        ContextSettings settings;
        settings.antialiasingLevel = 8;
        RenderWindow window(VideoMode::getDesktopMode(), "SFML works!",Style::Fullscreen,settings);
        RectangleShape shape(Vector2f(75, 75));
        shape.setFillColor(Color::White);

        //setting fixed time step loop
        float dt = 0.0f;
        float lastUpdateTime = 0.0f; //for now it's 0
        float accumulator = 0.0f;
        const float TIME_STEP = 1.f / 60.f; //for updating game 60 times per second
        const float MAX_ACCUMULATED_TIME = 1.0; //for make sure accumulator will not be too big
        Clock clock;
        clock.restart();

        while (window.isOpen())
        {
                Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == Event::Closed || (event.type == Event::KeyPressed && event.key.code == Keyboard::Escape))
                                window.close();
                }

                dt = clock.getElapsedTime().asSeconds() - lastUpdateTime; //calculating time since last frame
                lastUpdateTime += dt;
                dt = max(0.0f, dt); //to make sure dt is not less than 0
                accumulator += dt;
                accumulator = clamp(accumulator, 0.0f, MAX_ACCUMULATED_TIME); //for make sure accumulator is not too big (not bigger than 1 (second))
                while (accumulator > TIME_STEP)
                {
                        //update game, in this case moving object (with no class, just a few if()'s)
                        if (Keyboard::isKeyPressed(Keyboard::W))
                                shape.move(0, -180 * TIME_STEP);
                        if (Keyboard::isKeyPressed(Keyboard::S))
                                shape.move(0, 180 * TIME_STEP);
                        if (Keyboard::isKeyPressed(Keyboard::A))
                                shape.move(-180 * TIME_STEP, 0);
                        if (Keyboard::isKeyPressed(Keyboard::D))
                                shape.move(180 * TIME_STEP, 0);

                        accumulator -= TIME_STEP;
                }

                window.clear();
                window.draw(shape);
                window.display();
        }

        return 0;
}

Try this code, please. You will probably see not smooth movement with lags. But if you change this line:
const float TIME_STEP = 1.f / 60.f; //for updating game 60 times per second

... to this:
const float TIME_STEP = 1.f / 200.f; //for updating game 200 times per second

... you will probably see smooth movement, with no lags.

I think, you will see smooth movement only in second code, with TIME_STEP = 1.f / 200.f If not... I don't know what's wrong. I have no idea.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Laggy fixed time step loop
« Reply #12 on: June 07, 2016, 05:08:22 am »
This looks like the result of a different number of fixed timesteps being updated per cycle. This is perfectly normal but requires extra work to "smooth" out the final result.

In the three internet articles that you listed, consider reading the second one (Fix Your Timestep) as the final section (called "The Final Touch") is the part that fixes this.

The general idea is that, after you perform all updates in that cycle, you take the ratio of what is left in the accumulator of the timestep and then perform a linear interpolation between the (entire) state before the updates (at the start of the cycle) and the updated state - using the ratio as the interpolation's alpha/ratio.
This, technically, puts your display one frame behind but results in much more reliable movement than extrapolation as that is a prediction and is rarely perfect.

"Cycle" here is one time through the window loop, which would include a single display of the window (but possibly multiple logic/physics update).

Consider that you have a "cycle" rate of 60 fps whereas your logic is updated at 90 fps. Since logic updates are always applied in fixed amounts, it will update once on one cycle and twice on the next, constantly alternating between the two. This is the reason behind the stuttering. This is not exact either, so it's even less reliable.
After the first cycle has finished, only one logic update has happened but it "should" be half way through the next one. Since "half-way" is impossible with fixed steps, the previous values are interpolated with the current ones - exactly half way (as that is how much of the timestep should have happened at this point).

Provided with my small timing library, Kairos, is a class called Timestep that includes methods to simply return the interpolation alpha, which can be used for this interpolation. There is, in fact, a complete example of using this class to perform interpolations to smooth out motions (the example can also perform extrapolations for comparison). If you wish to avoid the library, you may still find the example of use to see (simple) interpolation in action.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

filipekczek7

  • Guest
Re: Laggy fixed time step loop
« Reply #13 on: June 07, 2016, 04:16:38 pm »
Hm, I have to read more about interpolation. Other guys (on other forum) told me not to worry about interpolation, because it's additional stuff, but my loop was laggy and I didn't know what's going on. So is interpolation often used stuff? Or it's not necessarily? Your statement shows that the interpolation is used and needed.
« Last Edit: June 07, 2016, 04:36:51 pm by filipekczek7 »

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Laggy fixed time step loop
« Reply #14 on: June 07, 2016, 05:12:47 pm »
I wouldn't say that it's "needed" but would be the additional step if you want to remove the slight stuttering feel while keeping the reliable nature of the fixed timestep for logic.
Notice, also, that the stuttering is less noticable when things are actually doing things. That is, changing shape or otherwise animating (rather than just smoothly moving a rigid object) can severly reduce apparent stuttering.

Since I now have the ability to capture decent video, I may make a video showing the difference between Kairos' Timestep example with and without interpolation.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*