Nick Bryan
Nick Bryan

Reputation: 23

SFML Game Development Book - Understanding FPS Calculation

this is my first post so I hope I get this right.

I'm currently working through the SFML Game Development Book. I am trying to understand how the FPS is calculated in the intro example.

My game class looks like this:

#include "Game.h"

const sf::Time Game::TIME_PER_FRAME = sf::seconds(1.f/60.f);
const float Game::PLAYER_SPEED = 100.f;

Game::Game() : Window(sf::VideoMode(640,480), "ORGELLA") {        

    isMovingUp = false;
    isMovingDown = false;
    isMovingLeft = false;
    isMovingRight = false;

    Player.setRadius(40.f);
    Player.setPosition(100.f, 100.f);
    Player.setFillColor(sf::Color::Cyan);

    font.loadFromFile(resourcePath() + "sansation.ttf");
    statsText.setFont(font);
    statsText.setPosition(5.f, 5.f);
    statsText.setCharacterSize(10);
}

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


    while (Window.isOpen()) {
        sf::Time dt = clock.restart();
        timeSinceLastUpdate += dt;

        while (timeSinceLastUpdate > TIME_PER_FRAME) {
            timeSinceLastUpdate -= TIME_PER_FRAME;

            handleEvents();
            update(TIME_PER_FRAME);
        }

        updateGameStats(dt);
        render();
    }
}

void Game::handleEvents() {
    sf::Event event;
    while (Window.pollEvent(event)) {
        switch (event.type) {
            case sf::Event::KeyPressed:
                handlePlayerInput(event.key.code, true);
                break;
            case sf::Event::KeyReleased:
                handlePlayerInput(event.key.code, false);
                break;
            case sf::Event::Closed:
                Window.close();
                break;
        }
    }
}

void Game::update(sf::Time dt) {
     sf::Vector2f movement(0.f, 0.f);

    if (isMovingUp)
        movement.y -= PLAYER_SPEED;
    if (isMovingDown)
        movement.y += PLAYER_SPEED;
    if(isMovingLeft)
        movement.x -= PLAYER_SPEED;
    if (isMovingRight)
        movement.x += PLAYER_SPEED;

    Player.move(movement * dt.asSeconds());
}

void Game::render() {
    Window.clear();
    Window.draw(Player);
    Window.draw(statsText);
    Window.display();
}

void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed) {
    switch (key) {
        case sf::Keyboard::W:
            isMovingUp = isPressed;
            break;
        case sf::Keyboard::S:
            isMovingDown = isPressed;
            break;
        case sf::Keyboard::A:
            isMovingLeft = isPressed;
            break;
        case sf::Keyboard::D:
            isMovingRight = isPressed;
            break;
    }
}

void Game::updateGameStats(sf::Time dt) {
    statsTotalTimeElapsed += dt ;
    statsNumberOfFrames += 1;

    if (statsTotalTimeElapsed >= sf::seconds(1.0f)) {
        statsText.setString(
            "FPS = " + to_string(statsNumberOfFrames) + "\n" +
            "Time/Update = " + to_string(statsTotalTimeElapsed.asMicroseconds() / statsNumberOfFrames) + "us");

        statsTotalTimeElapsed -= sf::seconds(1.0f);
        statsNumberOfFrames = 0;
    }
}

Now, my question is this. How is the FPS being calculated that is rendered to my screen. From what i can understand the FPS is capped at 60fps but yet when i run the application the FPS that is displayed is around 500 - 1200 FPS.

Am i calculating this wrong or just not understanding this correctly?

I hope this post is okay, I can't seem to find a similar question.

Any advice or help will be greatly appreciated.

Upvotes: 2

Views: 1163

Answers (2)

Nick Bryan
Nick Bryan

Reputation: 23

Figured this one out! I was looking at total frames ran per second and not frames updated per second. When i log how many times the update method gets run per second i get a steady 60FPS.

Appreciate the help.

Nick

Upvotes: 0

Shoe
Shoe

Reputation: 76240

Given a framerate (for example 60 FPS):

auto framerate = 60; // FPS
auto elapsedMillisecondsExpected = 1000 / framerate; // in milliseconds

In SFML you use an sf::Clock and at every frame you cap it:

sf::Clock clock;

// frame logic

auto elapsedMilliseconds = clock.getElapsedTime().asMilliseconds();
if (elapsedMilliseconds < elapsedMillisecondsExpected) {
    auto sleepMilliseconds = elapsedMillisecondsExpected - elapsedMilliseconds;
    // sleep for sleepMilliseconds
}

Upvotes: 1

Related Questions