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

Author Topic: Trying to implement DeWITTER's game loop.  (Read 6619 times)

0 Members and 1 Guest are viewing this topic.

Ante

  • Newbie
  • *
  • Posts: 1
    • View Profile
Trying to implement DeWITTER's game loop.
« on: January 22, 2013, 02:22:14 pm »
Hello. I'm trying to get the game loop from http://www.koonsolo.com/news/dewitters-gameloop/ to work on my project. The code works fine, however the interpolated object will stutter slightly while the non-interpolated object runs very smooth. I can't seem to figure out why and I was wondering if anyone could help me out with this.

Here's my code:

#include <SFML/Graphics.hpp>
#include <iostream>

const int TICKS_PER_SECOND = 25;
const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
const int MAX_FRAMESKIP = 5;

//StateManager TargetState;

int main()
{
    sf::RenderWindow Window(sf::VideoMode(800,600,32), "Test", !sf::Style::Resize | sf::Style::Close);

    // Game loop variables
    sf::Clock ticker;
    sf::Int32 next_game_tick = ticker.getElapsedTime().asMilliseconds();
    int loops;
    float interpolation;

    //TargetState.changeState(MenuState::Instance(&Window));

    while(Window.isOpen()) {
        //TargetState.input();

        // Update the game
        loops = 0;
        while(ticker.getElapsedTime().asMilliseconds() > next_game_tick && loops < MAX_FRAMESKIP) {
            //TargetState.update();
            next_game_tick += SKIP_TICKS;
            loops++;
        }

        interpolation = float(ticker.getElapsedTime().asMilliseconds() + SKIP_TICKS - next_game_tick)
                        / float (SKIP_TICKS);

        Window.clear();

        //TargetState.draw(interpolation);

        sf::Font font;
        font.loadFromFile("arial.ttf");
        sf::Text test("###", font, 250);
        sf::Text test2("###", font, 250);

        static float lex = 0.0;

        test.setPosition(lex + interpolation, 0);
        test2.setPosition(lex , 200);
        lex += 0.05;

        Window.draw(test);
        Window.draw(test2);

        Window.display();
    }
    return 0;
}
 

As you can probably see the top "###" stutters a bit while the bottom "###" runs very smoothly.
« Last Edit: January 22, 2013, 02:25:02 pm by Ante »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Trying to implement DeWITTER's game loop.
« Reply #1 on: January 22, 2013, 03:11:36 pm »
The big stutter comes from the fact, that you're reloading the font in every single loop iteration, which is quite a heavy operation. When you load it only once the stuttering is only minimal. I'm not quite sure what you're interpolation is doing and I don't really want to read the whole article, so maybe you could give a quick summary? What's the actual advantage over the one without + interpolate?

Anyways the problem probably is that you eventually can only display on integer coordinates (since 1px is the smallest resolution with an untouched view), thus moving between 0.0px and 1.0px well get rounded up or down and can sometimes lead to strange stuttering.

Here's the slightly modified code:
#include <SFML/Graphics.hpp>
#include <iostream>

const int TICKS_PER_SECOND = 25;
const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
const int MAX_FRAMESKIP = 5;

//StateManager TargetState;

int main()
{
    sf::RenderWindow Window(sf::VideoMode(800,600,32), "Test", !sf::Style::Resize | sf::Style::Close);

    // Game loop variables
    sf::Clock ticker;
    sf::Int32 next_game_tick = ticker.getElapsedTime().asMilliseconds();
    int loops;
    float interpolation;

    //TargetState.changeState(MenuState::Instance(&Window));

    sf::Font font;
    font.loadFromFile("arial.ttf");

    while(Window.isOpen()) {
        //TargetState.input();

        // Update the game
        loops = 0;
        while(ticker.getElapsedTime().asMilliseconds() > next_game_tick && loops < MAX_FRAMESKIP) {
            //TargetState.update();
            next_game_tick += SKIP_TICKS;
            ++loops;

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

        interpolation = float(ticker.getElapsedTime().asMilliseconds() + SKIP_TICKS - next_game_tick)
                        / float (SKIP_TICKS);

        Window.clear();

        //TargetState.draw(interpolation);

        sf::Text test("###", font, 250);
        sf::Text test2("###", font, 250);

        static float lex = 0.0;

        test.setPosition(lex + interpolation, 0);
        test2.setPosition(lex , 200);
        lex += 0.05;

        Window.draw(test);
        Window.draw(test2);

        Window.display();
    }
    return 0;
}
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

vivo

  • Jr. Member
  • **
  • Posts: 50
    • View Profile
    • Email
Re: Trying to implement DeWITTER's game loop.
« Reply #2 on: February 12, 2013, 01:57:53 pm »
You are adding the "lex" value to the interpolated one, whereas you should multiply the interpolated value with a constant value wich would represent a velocity factor.

view_position = position + (speed * interpolation)

for the bottom one, it's ok (and very smoothly) while your frame rate doen't suffer variations (your case).

view_position = position + "lex"(constant var: 0.05)

Also eXpl0it3r is right, no need to load the font at each frame

Roose Bolton of the Dreadfort

  • Full Member
  • ***
  • Posts: 113
  • Full-time Procrastinator, Part-time programmer.
    • View Profile
    • Personal Portfolio/Website/Blog
Re: Trying to implement DeWITTER's game loop.
« Reply #3 on: February 12, 2013, 03:20:33 pm »
Question..

Why not just use

App.setFramerateLimit(60);
 

Whats the difference between using that and implementing this?
Trying so very hard to finish at-least one project.

Watch out for the RAII police, they will get you.

www.bantersaurus-games.com

mateandmetal

  • Full Member
  • ***
  • Posts: 171
  • The bird is the word
    • View Profile
    • my blog
Re: Trying to implement DeWITTER's game loop.
« Reply #4 on: February 12, 2013, 03:56:08 pm »
Question..

Why not just use

App.setFramerateLimit(60);
 

Whats the difference between using that and implementing this?


Tally: by using setFramerateLimit, you are saying to your window: "Hey, dont draw more than x frames per second, please". With an implementation like this, you are not setting any limit on the FPS, you are just running the game (logic) at a fixed frame rate (in this case is 25 fps), and then using interpolation to smooth the animations.

I´m currently using the Fix Your Timestep! method.
- Mate (beverage) addict
- Heavy metal addict _lml
- SFML 2 addict
- My first (and free) game: BichingISH!

Roose Bolton of the Dreadfort

  • Full Member
  • ***
  • Posts: 113
  • Full-time Procrastinator, Part-time programmer.
    • View Profile
    • Personal Portfolio/Website/Blog
Re: Trying to implement DeWITTER's game loop.
« Reply #5 on: February 13, 2013, 11:32:55 am »
Okay, but limiting framerate is an okay way to go about it?
Trying so very hard to finish at-least one project.

Watch out for the RAII police, they will get you.

www.bantersaurus-games.com

vivo

  • Jr. Member
  • **
  • Posts: 50
    • View Profile
    • Email
Re: Trying to implement DeWITTER's game loop.
« Reply #6 on: February 14, 2013, 03:47:01 pm »
Okay, but limiting framerate is an okay way to go about it?
if your framerate is always higher than the limit: yes

mateandmetal

  • Full Member
  • ***
  • Posts: 171
  • The bird is the word
    • View Profile
    • my blog
Re: Trying to implement DeWITTER's game loop.
« Reply #7 on: February 14, 2013, 04:00:38 pm »
For a very little game, its ok

For a bigger proyect, specially if you have a physics engine, you need to implement this kind of game loop control
- Mate (beverage) addict
- Heavy metal addict _lml
- SFML 2 addict
- My first (and free) game: BichingISH!