0
\$\begingroup\$

I've been building an SFML engine and I've been very confused on the FPS, frame independent movement and game loop.

My particular problem is that I have a variable set to 60 for the frame limit but changing this value doesn't seem to change the frame limit. I used the built in SFML window function to set a limit and it seems to work.

Am I doing something wrong with this loop?

while (mWindow.isOpen())
{
    time=renderClock.getElapsedTime();
    float fFps=1000000/time.asMicroseconds();
    std::stringstream s;
    s<<fFps<<" fps";
    fps.setString(s.str());
    renderClock.restart();

    const sf::Int64 frameTime = 1000000/FRAMES_PER_SECOND;
    sf::Clock c;
    sf::Time t=c.getElapsedTime();
    sf::Int64 nextFrameTime=t.asMicroseconds()+frameTime;

    int loops = 0;
    while( t.asMicroseconds() < nextFrameTime && loops < MAX_FRAMESKIP)
    {
        processEvents();
        updateTime=updateClock.restart().asMilliseconds();
        update(updateTime);
        t=c.getElapsedTime();
        loops++;
    }

    render();
}

Here's a link to my full code: https://github.com/csharpest94/SFML/blob/master/src/Game.cpp

\$\endgroup\$
2
  • \$\begingroup\$ Can you check if you leave the second while loop because of t.asMicroseconds() < nextFrameTime or loops < MAX_FRAMESKIP, please ? You probably reach MAX_FRAMESKIP very fast if it is set to 10. \$\endgroup\$ – Heckel Apr 1 '15 at 14:21
  • \$\begingroup\$ yeah I tried changing the values of MAX_FRAMESKIP to a few different values and it didn't effect it. Also in debugging the value of t.asMicroseconds() came to about 54719757 and loops was equal to 1 \$\endgroup\$ – Csharpest Apr 1 '15 at 15:21
0
\$\begingroup\$

This might not be a solution to problem , but as far as I know main game loop should not be limited using sf::Window::setFramerateLimit(unsigned int limit). Only game logic, AI, physics should be limited, events should be processed without any limitation as not to create input lag.

I would suggest:

sf::Clock clock;
sf::Time accumulator = sf::Time::Zero;
sf::Time ups = sf::seconds(1.f / 60.f);

while (windows.isOpen())
{
    ProcessEvents();

    while (accumulator > ups)
    {
        accumulator -= ups;
        UpdateLogic();
        //AI();
        //Physics();
    }

    Render();
    accumulator += clock.restart();
}

Smooth movement can be easily implemented because logic runs at 60 updates per second, so if you want for instance sprite to move about 100px you need to divide this by 60 or in example above multiply with ups variable:

//pseudo code sprite.move(100 * ups); So every update your sprite will move for the same distance.

With this approach comes the danger that if you're not limiting game loop, your CPU will be working at high load, even if it's unnecessary. Unfortunately way to prevent this situation requires more complex game loops. Of course you can limit your render analogously and set it to be running at for example 100 frames per second, however that is not the best idea since there might be some issues if render can't keep up with fps - whole loop will be blocked.

I suggest you take a look at diagrams and descriptions in this article: http://entropyinteractive.com/2011/02/game-engine-design-the-game-loop/

About your problem, you can try implementing fixed time step loop I mentioned above with limiting main loop through sf::Window::setFramerateLimit(unsigned int limit).

\$\endgroup\$
0
\$\begingroup\$

Why not just use the sf::Window::setFramerateLimit(unsigned int limit) method? That should be a lot more straightforward and it works flawlessly for me.

EDIT:Just read you used it before. Gonna tell you something. Basic of rule of programmers. If it works, don't fix it.

\$\endgroup\$
4
  • \$\begingroup\$ But doesn't using the setFrameLimit method still leave a problem of frame dependant movement? :s Thats why I tried the loop in the first place \$\endgroup\$ – Csharpest Apr 1 '15 at 15:09
  • \$\begingroup\$ @Csharpest What problem does it leave? By coding the loop you are basically doing the same thing that method does. Limiting the framerate. \$\endgroup\$ – ChemiCalChems Apr 1 '15 at 15:14
  • \$\begingroup\$ Look at the code, he limits the framerate but not the rate at which the events are handled. \$\endgroup\$ – Heckel Apr 1 '15 at 15:24
  • \$\begingroup\$ @Heckel Well, I guess you are right, but the only thing SFML really does is after the display function is called it waits a bit to counter the framelimit. That's it really. So it shouldn't have any thing to do with how fast or how many times the events are handled per second. \$\endgroup\$ – ChemiCalChems Apr 1 '15 at 15:34
0
\$\begingroup\$

Your issue here is not that you are not using sf::Window::setFramerateLimit(unsigned int limit), but that you are only actually calculating your frameTime variable once, as it is really a constant.

All that you have to do is change:

const sf::Int64 frameTime = 1000000/FRAMES_PER_SECOND;

to:

sf::Int64 frameTime = 1000000/FRAMES_PER_SECOND;

and that should fix the issue since the frameTime will now be calculated once every loop.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.