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

Author Topic: Fix Your Time Step - New to SFML  (Read 5041 times)

0 Members and 1 Guest are viewing this topic.

Rutin

  • Newbie
  • *
  • Posts: 5
    • View Profile
Fix Your Time Step - New to SFML
« on: December 03, 2016, 03:35:21 am »
Hello everyone! I'm new to SFML, but come from using XNA, Allegro, and some SDL back in the day.

I've always been use to just having a function that kept my games at 60 FPS lock, and all game play, logic, rendering was done in the same loop, with no independent timers, 100% based on frames rendered.

I'm extremely interested in duplicating the Time Step as per the article: http://gafferongames.com/game-physics/fix-your-timestep/ but I'm running into some issues as I've never used Delta Time, or any methods prior, everything was handled for me before.

NOTE: I turned on VSYNC in my Window Class to keep the rate at 60 FPS.

My current code for main.cpp:

#include "Game.h"
#include <iostream>

int main()
{
        // Time Test
        sf::Clock MainClock;
        double Time = 0.0;
        const double DeltaTime = 0.01;

        double CurrentTime = MainClock.getElapsedTime().asSeconds();
        double Accumulator = 0.0;

        Game GameTest;

        while (GameTest.IsWindowOpen())
        {
                double NewTime = MainClock.getElapsedTime().asSeconds();
                double FrameTime = NewTime - CurrentTime;
                CurrentTime = NewTime;

                Accumulator += FrameTime;

                while (Accumulator >= DeltaTime)
                {
                        // Game Loop
                        GameTest.Input(DeltaTime);

                        GameTest.Logic(DeltaTime);

                        // AI
                        // Physics

                        Accumulator -= DeltaTime;
                        Time += DeltaTime;
                }
       
                // Render Graphics
                GameTest.Render();

                // FPS - Shows in Console Window
                std::cout << "FPS: " << 1.0f / FrameTime << std::endl;
        }

        return 0;
}
 

My game.cpp code for moving the sprite:

// Input
void Game::Input(double TempUpdatesPerSecond)
{
        // Keyboard Movement for guy1 --- TEST !!!
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
                guy1.move(0, -32 * TempUpdatesPerSecond);
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
                guy1.move(0, 32 *TempUpdatesPerSecond);
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
                guy1.move(32 * TempUpdatesPerSecond, 0);
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
                guy1.move(-32 * TempUpdatesPerSecond, 0);
        }
}
 

In the article I'm having trouble understanding what I do with Time? Why is it passed into my Update function along with Delta Time? Do I have my variables set up properly?

From the Article - Second Last Code Snip:

double t = 0.0;
const double dt = 0.01;

double currentTime = hires_time_in_seconds();
double accumulator = 0.0;

while ( !quit )
{
    double newTime = hires_time_in_seconds();
    double frameTime = newTime - currentTime;
    currentTime = newTime;

    accumulator += frameTime;

    while ( accumulator >= dt )
    {
        integrate( state, t, dt );
        accumulator -= dt;
        t += dt;
    }

    render( state );
}

I also have a cout to show how many frames per second are being rendered out to make sure it matches with vsync.

Since DeltaTime = 0.01; does this mean I'm moving at 0.01 * units per frame, at a maximum of 0.06 * units per second assuming steady 60 FPS with Vsync?

I would like to get my code working properly as to match the second last part of the article before learning how to do the final step. I also have no idea about interpolation.

I was also reading online that Delta Time is a very poor technique to use, and you should only program based on a fixed amount of ticks? My issue is making sure my games run good on 60 Hz or 200+ hz monitors while keeping the logic at a fixed update rate, and using any left over time to render as many frames as possible, I just need some guidance along the way.

Thank you!

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Fix Your Time Step - New to SFML
« Reply #1 on: December 06, 2016, 05:02:09 pm »
Hello everyone! I'm new to SFML, but come from using XNA, Allegro, and some SDL back in the day.
Hi! :)

Delta time represents the (theoretical) time passed since the last update of the game's logic. It therefore would be the "time step". If this varies (i.e. is the length taken since the previous frame update), there can be some extra problems introduced into logic/physics. Fixing the delta time (or time step) to a constant duration allows the logic to work in predictably regular chunks of time. Those are explained somewhat in the article you linked.

Time (t) would be the total time passed/processed. This is, therefore, your running time. Note that this time is how much time has been processed by the logic functions in the loop and is increased only by the timestep (dt) so t will always be a multiple of dt.

The interpolation part in "The final touch" can be rather difficult to grasp. Although its implementation is "simple", it may be a lot of work. Luckily it's not required and is avaiable if you want it to animate just that little bit smoother.

So, the point really is to fix the timestep (use a constant delta time) to update all of the logic and physics in equal pieces of time. If more actual time has passed, multiple of those updates will be required.

For example, if your refresh/update rate is at 60 FPS, and your logic is at 120 FPS (1.0 / 120.0), the logic updates will be performed twice (approximately) per cycle/tick/frame. If your logic is at 100 FPS (1.0 / 100.0 = 0.01, as yours is), The updates will be performed twice on some frames and once on others.

Since DeltaTime = 0.01; does this mean I'm moving at 0.01 * units per frame, at a maximum of 0.06 * units per second assuming steady 60 FPS with Vsync?
No.
As mentioned above, a delta time of 0.01 means that each time the logic is updated, time progresses by 0.01 seconds; that is 100 FPS/updates-per-second.

For example, if you move 1 unit in the logic update, it would move 100 units per second.

It's often a good idea to multiply motion by the dt so that the stated speed becomes more intuitive.
For example, if you want to move 100 units per second, you move (100 * dt) units in the logic update, it would move 100 * 0.01 = 1 unit per update. As above, since there are 100 updates per second, it becomes 100 units per second, as required.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*