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

Author Topic: Setting Frame Limit of the project  (Read 13036 times)

0 Members and 1 Guest are viewing this topic.

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Setting Frame Limit of the project
« on: September 18, 2019, 09:15:06 pm »
Hi, I’m learning SFML with “SFML Game Development” (https://www.amazon.com/SFML-Game-Development-Jan-Haller/dp/1849696845) and there is something I don’t understand about fixed time steps technique to give always the same delta time to the update function:

/*
When we are over the required amount for one frame, we substract
desired length of this frame (TimePerFrame) and update the game.
*/

void Game::run()
{
    sf::Clock clock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;

    while(mWindow.isOpen())
    {
        processEvents();

        timeSinceLastUpdate += clock.restart();
       
        // collects the user input and computes the game logic.
        while (timeSinceLastUpdate > TimePerFrame)
        {
            timeSinceLastUpdate -= TimePerFrame;
            processEvents();
            update(TimePerFrame);    
        }        
        render();
    }
}

So we accumulate the elapsed time in timeSinceLastUpdate and substract the desired length of this frame (TimePerFrame = 1.f /60.f) and do this until we are below the required amount again ant then render the scene (this is called logic frame rate). With this the frame rate is 60 fps.

With this, if rendering is slow, processEvents()  and update() may be called multiple times before one render() call, so the game occasionally slutters becuase not every update is rendered, but the game doesn’t go slow down. On the other hand fast rendering can lead to call render() multiple times without a logic update in between.

Ok, the problem of this method is that CPU usage is high (about 50% or more).

Then I can use sf::RenderWindow::setFrameLimit(60) that calls sleep() internally but lacks precision, and then is sf::RenderWindow::setVerticalSyncEnabled() that adapts the graphical updates to the refresh rate of the monitor (GPU I think).

My question is about what method do you usually use: and accurate method like first, the setFrameLimit function or the setVerticalSyncEnabled()? And if the answer is the first one, how do you solve the problem of the CPU usage?

Thanks to everyone.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Setting Frame Limit of the project
« Reply #1 on: September 18, 2019, 10:26:55 pm »
Hello, and welcome to the SFML forum! I hope that as one of the authors, I can give you a slightly more detailed answer than in the book ;)

In general, as long as your code runs, you will use 100% of one CPU core, or 50% of a dual-core processor -- after all, there are constantly new instructions being processed. The only way how you can decrease CPU utilization is by giving back CPU time to the operating system (or force it to be taken, if other resources are competing). This is typically done using sleep statements (sf::sleep() in SFML) or through blocking I/O (in multiple threads, you may wait for events or incoming network packets).

A very good article about game loops can be found here. It explains the fixed timestamp approach from our book and compares different trade-offs:
https://gameprogrammingpatterns.com/game-loop.html

The sleep's precision depends on which system call is used and how the system is configured. In this StackOverflow answer you'll find an in-depth explanation of the topic. There are also high-precision implementations (e.g. Windows or Linux), although they are typically not needed.

So, you have the following options:
  • Use all the CPU you get (highest precision, only recommended for really computation-intense simulations where you can't afford trade-offs, or you can use the extra CPU time for enhanced gameplay (AI etc.))
  • Standard sleep (usually good enough)
  • Tweaked sleep or alternatives (timers etc, see link)
  • VSync (easiest for graphics, aligns refresh rate with monitor)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Setting Frame Limit of the project
« Reply #2 on: September 22, 2019, 06:30:13 pm »
Thanks for the response, I'm a web developer so this is new for me (on web development I don't have this type of problems XD ).

So the idea of make games are simple 2D games for the moment. The first one would be an RPG like Final fantasy I ().

I think I don't need higher precision (this would not be an AAA game) so I don't want to use 100% CPU. So I'm between using Standard sleep (usually good enough) and try Vsync in the future.

Now I will search for use standard sleep.

PD: I develop on a laptop, so it heads up easily if the usage of CPU is 100%.
« Last Edit: September 22, 2019, 06:34:46 pm by albert_lazaro »

jamesL

  • Full Member
  • ***
  • Posts: 124
    • View Profile
Re: Setting Frame Limit of the project
« Reply #3 on: September 24, 2019, 07:12:26 pm »

So, you have the following options:
  • VSync (easiest for graphics, aligns refresh rate with monitor)

is VSync really an option ? 

I see a bunch of example SFML and SDL games that set the vsync option, but can't the player disable that globally ?

so relying on that wouldn't work, right ?

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Setting Frame Limit of the project
« Reply #4 on: September 29, 2019, 07:35:41 pm »
I think Vsync would have to be configurable by the user in a option menu, but you can't be sure it will work 100% of times.

There is more info in the tutorials -> https://www.sfml-dev.org/tutorials/2.0/window-window.php#controlling-the-framerate

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Setting Frame Limit of the project
« Reply #5 on: December 04, 2019, 07:28:38 pm »
Hi I skipped the loop problem to focus on the book, and now that I had advanced more I want to solve the loop problem because I don't want to burn my computer every time I'm executing my code for testing.

I want to use standard sleep, so in the main loop I have to write the sleep at the end of the outer loop? How many time it has to be sleeping?

void Game::run()
{
    sf::Clock clock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;

    while(mWindow.isOpen())
    {
        processEvents();

        timeSinceLastUpdate += clock.restart();
       
        // collects the user input and computes the game logic.
        while (timeSinceLastUpdate > TimePerFrame)
        {
            timeSinceLastUpdate -= TimePerFrame;
            processEvents();
            update(TimePerFrame);    
        }        
        render();
        <- here goes sleep ?
    }
}
 

If you see the video of above in this thread, you will see what type of game I want to do, so for this game I don't think it is necessary that the computer is working at 100% of cpu
« Last Edit: December 04, 2019, 07:33:36 pm by albert_lazaro »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11047
    • View Profile
    • development blog
    • Email
Re: Setting Frame Limit of the project
« Reply #6 on: December 05, 2019, 09:54:50 am »
SFML already has such a functionality with setFramerateLimit().

You'd sleep the amount of time, that would still make your reach the desired frame time.
Say you want 60fps <=> 16.666ms, now your last frametime was 4ms, so you could in theory sleep 16-4ms = 12ms.
However, sleeping is not a precise action, so you need to consider some slack, if you really want to precise.
(If you want to go crazy, you can also measure the deviation and adjust dynamically)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Setting Frame Limit of the project
« Reply #7 on: December 21, 2019, 08:32:23 pm »
I have seen the code of setFrameRateLimit:

void Window::setFramerateLimit(unsigned int limit)
{
    if (limit > 0)
        m_frameTimeLimit = seconds(1.f / limit);
    else
        m_frameTimeLimit = Time::Zero;
}
 

Can I combine it with my game loop? so before the loop starts I set the frame rate to 60 and then the loop is executed.

I don't know if, after the display is executed and the process goes to sleep, the time of clock is counting.