SFML community forums

Help => General => Topic started by: CasualKyle on August 11, 2016, 08:02:20 am

Title: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 11, 2016, 08:02:20 am
So the movement in my game isn't smooth. It looks like every tenth of a second the game freezes for a very short period of time then continues along until it freezes again.

You can see here as the rectangle moves, it stops for a short while then continues along.

(http://i.imgur.com/Ng5mUaE.gif)

Here is my code for updating and rendering the game:

float dt = 1.0 / 60.0f;
float accumulator = 0.0f;

while (window.isOpen())
{
        float frameTime = clock.restart().asSeconds();
        accumulator += frameTime;

        while(accumulator >= dt)
        {
                pollEvents();
                updateStates(dt);
                clearInput();

                accumulator -= dt;
        }

        window.clear();
        drawStates(window);
        window.display();
}
 

Is my code flawed in someway and is this behavior a result of it? Or should this create smooth movement and thus the problem is with something else?
Title: Re: Strange Movement with Fixed Timestep
Post by: Mr_Blame on August 11, 2016, 01:36:14 pm
I should better use window.setFramerateLimit
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 11, 2016, 09:15:07 pm
I should better use window.setFramerateLimit

I've experimented with this function before and if it set it to the match the frame rate I've implemented in my code it has no visual impact which would make since because it just checks to see if an amount of time has passed before displaying the contents.

I've decided to experiment a little more with it though. Here's what I changed the code to:

window.setFramerateLimit(60);

while (window.isOpen())
{
    pollEvents();
    updateStates(dt);
    clearInput();

    window.clear();
    drawStates(window);
    window.display();
}

So after making this change I noticed that the movement is the same, it's not smooth. This tells me that the code I wrote in the first post is probably fine and that the issue is elsewhere. I figured maybe it's my computer so I ran the application on a different less powerful computer and strangely the movement is smooth! Now that I think about it this issue started happening when I applied the windows 10 anniversary update to my computer. The graphics drivers are up to date so I have absolutely no clue why this would be happening. Does anyone have any ideas?
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 12, 2016, 03:35:35 am
Fixed Timestep creates a reliable and regular update for physics and logic. It doesn't, however, fix the refresh rate of the window. This is decided by the OS; if it would prefer to do something else, your window will have to wait.
Therefore, each frame shown isn't guaranteed to be perfectly regular and, in some cases, not at the exact time you expect a frame - it could be part way.
Frame interpolation can help solve this visual artifact. It's the very last part in the Fix Your Timestep article. I commented about this here recently and there is a small accompanying video to that comment showing the difference. See the comment here (http://en.sfml-dev.org/forums/index.php?topic=20655.msg148416#msg148416) (also includes a link to Fix Your Timestep article).
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 12, 2016, 08:49:45 am
Fixed Timestep creates a reliable and regular update for physics and logic. It doesn't, however, fix the refresh rate of the window. This is decided by the OS; if it would prefer to do something else, your window will have to wait.
Therefore, each frame shown isn't guaranteed to be perfectly regular and, in some cases, not at the exact time you expect a frame - it could be part way.
Frame interpolation can help solve this visual artifact. It's the very last part in the Fix Your Timestep article. I commented about this here recently and there is a small accompanying video to that comment showing the difference. See the comment here (http://en.sfml-dev.org/forums/index.php?topic=20655.msg148416#msg148416) (also includes a link to Fix Your Timestep article).

I looked at your video and it appears the same issue is happening with me so I implemented interpolation but unfortunately the issue is still there. Here is a minimal code example which is also on github (https://github.com/CasualKyle/TimestepTesting):

main.cpp
#include "State.h"

int main()
{
        sf::RenderWindow window(sf::VideoMode(1500, 1000), "Timestep Testing");
        window.setKeyRepeatEnabled(false);

        State state;

        sf::Clock clock;
        float dt = 1.0f / 60.0f;
        float accumulator = 0.0f;

        while(window.isOpen())
        {
                sf::Event event;
                while(window.pollEvent(event))
                        if(event.type == sf::Event::Closed)
                                window.close();

                accumulator += clock.restart().asSeconds();

                while(accumulator >= dt)
                {
                        state.update(dt);
                        accumulator -= dt;
                }

                float interp = accumulator / dt;

                window.clear();
                state.draw(window, interp);
                window.display();
        }

    return 0;
}

State.h
#pragma once

#include "SFML\Window.hpp"
#include "SFML\Graphics.hpp"

class State
{
public:
        State();

        void update(float timeStep);
        void draw(sf::RenderWindow& window, float interp);

private:
        sf::RectangleShape rect;
        sf::Font font;
        sf::Text fps;
        sf::Text dps;
        sf::Clock clockUpdate;
        sf::Clock clockDraw;
        int frames;
        int draws;
        sf::Vector2f pos;
        sf::Vector2f lastPos;
};

State.cpp
#include "State.h"

State::State() : rect(sf::Vector2f(100.0f, 100.0f))
{
        font.loadFromFile("lucon.ttf");
        fps.setFont(font);
        dps.setFont(font);
        fps.setPosition(10.0f, 0.0f);
        dps.setPosition(10.0f, 30.0f);
        frames = -1;
        draws = -1;
}

void State::update(float timeStep)
{
        if(clockUpdate.getElapsedTime().asSeconds() >= 1.0f) {
                fps.setString("FPS: " + std::to_string(frames));
                frames = 0;
                clockUpdate.restart();
        }

        frames++;

        sf::Vector2f d;

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W))
                d.y = -1;

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S))
                d.y = 1;

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A))
                d.x = -1;

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D))
                d.x = 1;

        lastPos = pos;

        pos += 150.0f * d * timeStep;
        rect.setPosition(pos);
}

void State::draw(sf::RenderWindow& window, float interp)
{
        if(clockDraw.getElapsedTime().asSeconds() >= 1.0f) {
                dps.setString("Draw Calls: " + std::to_string(draws));
                draws = 0;
                clockDraw.restart();
        }

        draws++;

        window.draw(fps);
        window.draw(dps);

        sf::Vector2f posInterp = pos * interp + lastPos * (1.0f - interp);
        rect.setPosition(posInterp);
        window.draw(rect);
}

I'm getting a solid 60 frames per second and around 800 draw calls per second but the movement is still noticeably jittery. I also noticed that if I comment out the following code from main.cpp the issue goes away and the movement is buttery smooth.

sf::Event event;
while(window.pollEvent(event))
        if(event.type == sf::Event::Closed)
                window.close();

It appears that calling window.pollEvent() is causing the movement to be jittery.
Title: Re: Strange Movement with Fixed Timestep
Post by: K.F on August 12, 2016, 11:01:15 am
Looks smooth to me when I compile it. Maybe a Driver, or a GPU global settings issue?
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 12, 2016, 12:19:45 pm
If the event loop is slowing down your window, it could be that the window is receiving too many events from the OS. Maybe something is causing it to do that.

I'm getting a solid 60 frames per second and around 800 draw calls per second
How? If you are drawing 60 frames per second and drawing three things per frame, you should be getting 180 draw calls per second.
Title: Re: Strange Movement with Fixed Timestep
Post by: Mr_Blame on August 12, 2016, 02:02:19 pm
Oh, in your draw function you are calling std::to_string which returns a newly allocated string a think, that allocating something very frame may cause lagging as I experienced it myself.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 12, 2016, 04:22:11 pm
you are calling std::to_string [...] [e]very frame [...] may cause lagging as I experienced it myself.
Using std::to_string every frame is absolutely fine. How else are you expected to display the latest scores, times etc.?
Title: Re: Strange Movement with Fixed Timestep
Post by: Demir on August 12, 2016, 06:20:58 pm
Quote
Using std::to_string every frame is absolutely fine. How else are you expected to display the latest scores, times etc.?

I'm not sure

may be sprintf (considered unsafe) function instead of to_string.
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 12, 2016, 09:29:16 pm
I'm getting a solid 60 frames per second and around 800 draw calls per second
How? If you are drawing 60 frames per second and drawing three things per frame, you should be getting 180 draw calls per second.

Sorry, I meant that the state.draw() function is getting called about 800 times per second. This doesn't seem irregular to me because since state.draw() is inside the while(window.isOpen()) loop it's going to get lots and lots of calls basically as fast as the CPU can do it.

When I run the minimal application on a different less powerful I get again a solid 60 frames per second and about 400 calls to state.draw() per second which would make since seeing that it's got a Pentium processor and my main computer has a core i7. (I know the CPU isn't everything and if you want the full specs of each computer I can give them to you.) And the movement is smooth. So I don't know I feel like the issue isn't with the code.

Okay so here is how I can get the movement to be smooth:
sf::Event event;
while(window.pollEvent(event))
    if(event.type == sf::Event::Closed)
        window.close();

I said this before but this only started happening after I applied the Window 10 anniversary update to my computer which was August 1st if I remember correctly. I've ran the Intel Driver Update Utility (http://www.intel.com/content/www/us/en/support/detect.html?iid=dc_iduu)  and it does not return back that the graphics drivers are not up to date.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 12, 2016, 09:38:50 pm
If you're getting 800 draw calls per second and you're calling it once per frame, you're getting (internally) 800 frames (or ticks/cycles) per second. That is, the interpolation is not interpolating between the previous "seen" position and the current position but the previous position at the previous frame. This pretty much removes the effect for which interpolation is used so try limiting your framerate (something like 60-80) or activating v-sync (but not both). I think this is not a very good explanation so I apologise. Anyway, your logic should probably be running higher that the speed of the refresh/frame rate.
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 13, 2016, 08:25:18 am
If you're getting 800 draw calls per second and you're calling it once per frame, you're getting (internally) 800 frames (or ticks/cycles) per second. That is, the interpolation is not interpolating between the previous "seen" position and the current position but the previous position at the previous frame. This pretty much removes the effect for which interpolation is used so try limiting your framerate (something like 60-80) or activating v-sync (but not both). I think this is not a very good explanation so I apologise. Anyway, your logic should probably be running higher that the speed of the refresh/frame rate.

I did some more research, looked at your implementation with your Kairos timing library, changed my code and still didn't notice a change. Then I just downloaded your library altogether and used the timeStepExample.cpp example. I changed the timestep to be 1 / 30 because updating the physics 5 times a second made the circle move 250 * (1 / 5) = 50 pixels each physics update which is quite a jump. Anyway after doing that and experimenting with the interpolation and extrapolation and I can tell you that it doesn't make the movement smooth on my computer.

Sorry the dimensions are so big. Here's the link. (http://i.imgur.com/vtRl7zV.gif)
(http://i.imgur.com/vtRl7zV.gif)

Here's what I conclude from messing around with your application. There is cyclic behavior with how the circle moves: It's smooth then a freeze, smooth then a freeze, smooth then a freeze, etc. The cycle seems to repeat about once every fith of a second. And the only line of code I changed was this: timestep.setStep(1.0 / 30.0);. Now it's hard to tell the difference but when I turn interpolation on, the movement between the freezes does look smoother, however the freezes are still there.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 13, 2016, 12:54:28 pm
I may be seeing things but it looks like "Time passed" is stuttering when the circle does. This would suggest that the window itself is being delayed.
I guess the most important (you might think it's too obvious) but required unasked questioned is:
Is this on a release build or does it only occur during debug builds?

There was no need to change the timestep in that example to 1/30 from 1/5; you can toggle between 1/5 and 1/60 by pressing Space. The resulting timestep information text in the title bar is showing 1/60 because it's expecting either 1/5 or 1/60 so chooses one. tl:dr; Use the example as is and press Space  :P

Just so you know, the 1/5 is there to show just how much interpolation does. Running at 1/5 with interpolation switched on has motion that is as smooth as 1/60 with interpolation on.  ;)
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 13, 2016, 10:39:36 pm
There was no need to change the timestep in that example to 1/30 from 1/5; you can toggle between 1/5 and 1/60 by pressing Space. The resulting timestep information text in the title bar is showing 1/60 because it's expecting either 1/5 or 1/60 so chooses one. tl:dr; Use the example as is and press Space  :P

Just so you know, the 1/5 is there to show just how much interpolation does. Running at 1/5 with interpolation switched on has motion that is as smooth as 1/60 with interpolation on.  ;)

Oh okay I didn't notice the code that changed the time step to 1/60 when the space bar is pressed and yeah, using interpolation while the time step is 1/5 sure does show you how beneficial interpolation can be.

I may be seeing things but it looks like "Time passed" is stuttering when the circle does. This would suggest that the window itself is being delayed.
I guess the most important (you might think it's too obvious) but required unasked questioned is:
Is this on a release build or does it only occur during debug builds?

It does look a little like the "Time passed" is stuttering when the circle does in the gif. But when it's running on my computer the "Time passed" doesn't stutter. I think it just didn't record the application as well as it runs. And as for the question of if there's a difference with it running on a release vs a debug build. No there is not, I get the same stuttery movement regardless of if it's a release or debug build.

Could be valuable information: Like with my application commenting out this code in your example makes the issue go away:
sf::Event event;
while(window.pollEvent(event))
{
        ...
}
 
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 14, 2016, 12:11:58 am
Try timing the frames and outputting that information to see if there any unusual spikes.

Like with my application commenting out this code in your example makes the issue go away:
sf::Event event;
while(window.pollEvent(event))
{
        // ...
}
You shouldn't remove this. It's very important that a window deals with its events. Every application must do this; if it doesn't, the operating system is likely to consider the application as unresponsive/crashed and may close it.
Plus, how else would you close the window? ;D
Title: Re: Strange Movement with Fixed Timestep
Post by: Mr_Blame on August 14, 2016, 10:06:06 am
This may be std::queue allocation issue(SFML uses std::queue for event handling)
Title: Re: Strange Movement with Fixed Timestep
Post by: Carlitox on August 14, 2016, 11:50:17 am
I'm having the same problem but only in the window mode and no so often, it's a stuttering that happens suddendly each 2 seconds when moving the map at high velocity.

I'm using kairos and doing interpolation at 60 fps. What i look strange is that fps is 59.5 and not 60 in the computer that causes the problem.

PD: It seems a problem of cpu or memory usage because if i restart laptop and pc it doesn't happen the stuttering. It comes with time.
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 14, 2016, 04:19:56 pm
Try timing the frames and outputting that information to see if there any unusual spikes.

I'm restarting an sf::Clock just before the window is rendered. Then I'm subtracting away the previous frame time from that time and printing out "--- stutter ---" if the difference is > 0.05. Okay so during the simulation I noticed it stuttered about 5 or 6 times (I didn't run the application for very long) and this is the output (http://pastebin.com/uXVzkWLm) which you can see 6 times "--- stutter ---" was printed. So yeah it looks like the window isn't getting rendered consistently.

I'm holding down the right arrow key so as soon as the application starts the circle moves to the right and when it get's to the end I close it down so the application isn't running for very long. Then I'm printing out the x position of the circle and if the current position - previous position > 5 I'm printing out "--- stutter ---". Here's the output (http://pastebin.com/xaDVejkF) for the x position of the circle. If you put the two outputs side by side the stutter output line's line up (http://imgur.com/a/Umzku). (Also the position of the circle is being rounded which is why they're whole numbers)

PD: It seems a problem of cpu or memory usage because if i restart laptop and pc it doesn't happen the stuttering. It comes with time.

Same with me when I restart my  computer it goes away just to come back later in the day.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 14, 2016, 08:10:47 pm
"- stutter -"
Yes, it looks like your frame is being delayed quite unusually. Try closing other things you have running to see if it's being affected by those. Also, try running the built release executable directly.

If those still cause the delayed frames, try increasing their priority to see if that changes anything; it could be an indication that something is hogging the CPU when it wants to use it.

Make sure your graphics card drivers are up-to-date.

Note: rounding positions helps with displaying pixel accuracy but can also create its own stuttering affect as whole number aren't the exact position that it should be. You could try without rounding to see if it helps with motion.
Title: Re: Strange Movement with Fixed Timestep
Post by: Carlitox on August 14, 2016, 09:47:56 pm
If the positions are interpolated to make smooth movements that means that i must use non integer values for moving views. ¿That will cause problems? ¿What i should do?

I was using this function to store the decimals and only setting positions with integer values.

void Movement::moveNowInteger(sf::Vector2f n)
{
        if(n.x > 0.f) process_move_right += n.x;
        if (n.x < 0.f) process_move_left += (-n.x);
        if (n.y > 0.f) process_move_down += n.y;
        if (n.y < 0.f) process_move_up += (-n.y);
       
        if (process_move_right > 1.f)
        {
                moveNow(sf::Vector2f(std::floor(process_move_right), 0.f));
                process_move_right -= std::floor(process_move_right);
        }
        else if (process_move_left > 1.f)
        {
                moveNow(sf::Vector2f(-std::floor(process_move_left), 0.f));
                process_move_left -= std::floor(process_move_left);
        }

        if (process_move_down > 1.f)
        {
                moveNow(sf::Vector2f(0.f, std::floor(process_move_down)));
                process_move_down -= std::floor(process_move_down) ;

        }
        if (process_move_up > 1.f)
        {
                moveNow(sf::Vector2f(0.f, -std::floor(process_move_up)));
                process_move_up -= std::floor(process_move_up);
        }
}

Currently i'm integrating your kairos library to my game and i can move the view with a smooth movement and without flickering. The problem comes when i keep the program 1 minute or more moving the camera, it begins stuttering exaggeratedly.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 14, 2016, 10:02:58 pm
If it stuttering when moving the view (your camera is a view?), it could be the way you update based on the current view that is slowing things down. Are you drawing everything offscreen at all times as well, or are you only drawing things that are visible by testing to see if they're in the view?

Non-integer values can be fine. They can cause troubles with some rasterisation - with textures in particular. You can use integer values to help avoid these troubles, which include gaps in tilemaps. However, using integer values for positions when in motion mean that the values aren't exactly correct and therefore can cause a slight stuttering effect. In this case, it's a tradeoff: smooth motion or perfect rasterisation. There are, of course, other ways to avoid rasterisation troubles. They depend on the troubles you are facing.

Is this a tile map over which you are moving the camera?
Title: Re: Strange Movement with Fixed Timestep
Post by: Carlitox on August 15, 2016, 01:43:08 am
If it stuttering when moving the view (your camera is a view?), it could be the way you update based on the current view that is slowing things down. Are you drawing everything offscreen at all times as well, or are you only drawing things that are visible by testing to see if they're in the view?

Non-integer values can be fine. They can cause troubles with some rasterisation - with textures in particular. You can use integer values to help avoid these troubles, which include gaps in tilemaps. However, using integer values for positions when in motion mean that the values aren't exactly correct and therefore can cause a slight stuttering effect. In this case, it's a tradeoff: smooth motion or perfect rasterisation. There are, of course, other ways to avoid rasterisation troubles. They depend on the troubles you are facing.

Is this a tile map over which you are moving the camera?

The vertex array was 100x100 tiles with 4 layers  :P

I made it 40x10 and had the same issue but with lower cpu.

The problem was in the transitions between scenerios, i move the camera like in megaman and then run a lua script to load enemies that causes  fps go from 60 to 55 generating the graphics corruption with the time. Having mozilla opened causes a little stuttering every minute but not causes the massive corruption of graphics like the script.

Tomorrow i will play more time and see if the problem is reproduced or not. I have to work in an algorithm to resize the vertex array every second to allow big levels at low cpu and less memory usage.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 15, 2016, 04:13:53 am
The problem was in the transitions between scenerios, i move the camera like in megaman and then run a lua script to load enemies that causes  fps go from 60 to 55 generating the graphics corruption with the time.
Is this file access?
Does this camera move still stutter without this loading?
Title: Re: Strange Movement with Fixed Timestep
Post by: Carlitox on August 16, 2016, 05:55:01 pm
The problem was in the transitions between scenerios, i move the camera like in megaman and then run a lua script to load enemies that causes  fps go from 60 to 55 generating the graphics corruption with the time.
Is this file access?
Does this camera move still stutter without this loading?

The problem has been solved and has nothing to do with scripts, just was a collateral effect. The problem was that i was updating everything in this loop

while (timestep.isTimeToIntegrate())
{

..
update(dt);
 ..

}

Now i'm updating with your library in my MovementComponent class and in the Camera class and i quit this checking in the gameloop. I need to read more about time controlling and understand better your library.

Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 16, 2016, 09:48:59 pm
I'd highly recommend using Timestep instead of TimestepLite; it does more of the work for you.

If you have any questions about Kairos (or any of my libraries/projects), feel free to ask; I'll help the best I can.
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 17, 2016, 06:35:08 am
So I updated my graphics drivers which was actually one of the first things I thought to do upon encountering this issue. The problem was that I was using the Intel Driver Update Utility tool which told me that my graphics drivers did not need to be updated. It turns out they were not up to date. It's been over two days now and I have not experienced the issue since manually updating the drivers. I'll report back if I experience it again but for now if anyone has the same problem with their application go to the manufacture's website and download and install the graphics drivers manually. If you have integrated graphics on an Intel CPU do not trust the Intel Driver Update Utility tool it did not show that my graphics drivers were not up to date so it might do the same to you.
Title: Re: Strange Movement with Fixed Timestep
Post by: CasualKyle on August 17, 2016, 09:06:57 am
Never mind the issue is back, updating the graphics drivers did not work.

Yes, it looks like your frame is being delayed quite unusually. Try closing other things you have running to see if it's being affected by those. Also, try running the built release executable directly.

No change.

If those still cause the delayed frames, try increasing their priority to see if that changes anything; it could be an indication that something is hogging the CPU when it wants to use it.

Also no change.

Make sure your graphics card drivers are up-to-date.

I've done so, no change.
Title: Re: Strange Movement with Fixed Timestep
Post by: Carlitox on August 17, 2016, 12:57:08 pm
Put updateStates(dt) after the while loop not in it and before the rendering and activate vsync and look what happens.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on August 17, 2016, 07:35:45 pm
Put updateStates(dt) after the while loop not in it and before the rendering and activate vsync and look what happens.
That would defeat the object of fixed timestep and each update would happen once per frame regardless of how long that frame took.
Title: Re: Strange Movement with Fixed Timestep
Post by: willm127 on September 27, 2016, 10:42:47 pm
Hapax, just wanted to comment on here and say thanks for all of your help with this stuff. I've used Kairos on my last couple of projects, and it has made such a huge difference! I'm on a Macbook Pro, and even then, I noticed that the game would also stutter, especially when listening to music on YouTube in the background. What fixed the stuttering on my end was adding setVerticalSyncEnabled to the window. Movement is now smooth—even while running YouTube!

Just adding my experience here in case it helps anyone else in the future. If anyone else wants more details, especially for those on Mac, do let me know and I'll add those here.
Title: Re: Strange Movement with Fixed Timestep
Post by: Hapax on September 29, 2016, 08:33:57 pm
Hapax, just wanted to comment on here and say thanks for all of your help with this stuff. I've used Kairos on my last couple of projects, and it has made such a huge difference!
You are very welcome. I am glad you find Kairos useful! I use it myself, you know... :D

@CasualKyle, it's been a while so I can't remember: are you using vertical synchronisation?