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

Author Topic: Frames at the time  (Read 1473 times)

0 Members and 1 Guest are viewing this topic.

Rementh

  • Newbie
  • *
  • Posts: 6
    • View Profile
Frames at the time
« on: September 04, 2014, 10:08:55 am »
Hello, i've been working on a game project recently, and i already implemented some stuff, i have collisions, entities, bullets, movable camera. But after all this, i am still wondering about how to handle frames per second. Right now my code works on a simple principle, it measures the time of each frame and move the objects with constant speed multiplayed by that time:

float delta = clock.restart().asSeconds();
...
hero.sprite.move(hero.h_speed * delta, hero.gravity_delta * delta);

Works? Works. But looks a little poor, becouse i have to keep an eye on every single movement instruction and i'm pretty sure it could be done better. I've already tried the "update()" method which updates all the game logic by a constant time, but i don't like it, becouse i have to set the FPS limit then, and if the PC isn't good enough to handle it, the game works slower. How do all of these big games do it? I'd like to implement a method which will let me to keep the game logic in one separate function, but also does not force me to set the constant FPS and works with exact same speed on every computer, no matter if it's 15 or 150 FPS.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Frames at the time
« Reply #1 on: September 04, 2014, 10:49:50 am »
Laurent Gomila - SFML developer

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Frames at the time
« Reply #2 on: September 04, 2014, 11:09:20 am »
http://fabiensanglard.net/timer_and_framerate/index.php

You don't need constant FPS but you should have constant logic update rate, many (most?) games do logic at fixed timestep and interpolate rendering or drop some frames so their logic has constant rate and rendering is dependant on how much a target device can do.

This is honestly a very good way to do it, it's actually easier to program that way, it avoids precision errors, it's very predictable and allows many features like recording demos and so on almost automatically.
Also - some physics middleware requires fixed timestep too, I know for sure Box2D (a very popular 2D engine, used in Angry Birds which is insanely popular game for smartphones) does, possibly Bullet (a very good 3D engine, it's improved version is what runs in GTA 4 and 5)  too, I can't remember that now.
Back to C++ gamedev with SFML in May 2023

Rementh

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Frames at the time
« Reply #3 on: September 11, 2014, 10:28:09 am »
Thank you Laurent and FRex, i fixed timestep in my game, and now it works exactly how i wanted. The same speed with different frame rates, clear code, no bugs like objects falling through the floor or disappearing when i move the window, also clear physics, no matter if the frame rate is 5 or 500 FPS. Here's the source code of my game object:

Game::Game(void)
: window(sf::VideoMode(window_size_x, window_size_y), "Ambient"),
view(sf::FloatRect(0, 0, float(window_size_x), float(window_size_y))),
updateFPS(1000),
dt(1.0f / updateFPS),
elapsedTime(0.0f),
accumulator(0.0f),
currentTime(clock.getElapsedTime().asMilliseconds())
{
        init();
}
 

And game run() function:

void Game::run()
{
        while (window.isOpen())
        {
                /* Events */
                EventHandling();

                /* Timestep */
                newTime = clock.getElapsedTime().asMilliseconds();
                frameTime = static_cast<float> (newTime - currentTime) / 1000.0f;
                if (frameTime > 0.25f) frameTime = 0.25f;
                currentTime = newTime;
                accumulator += frameTime;
                while (accumulator >= dt)
                {
                        elapsedTime += dt;
                        accumulator -= dt;
                        /* Game Logic Update */
                        GameLogicUpdate();
                }

                /* View */
                View();

                /* Draw */
                Draw();
        }
}

Problem solved.