Search code examples
c++frame-rate

Setting fixed FPS doesn't work


I am working on a 2D game for a school project. The template my teacher gave works well, but I wanted to replace a very, very stupid thing in the code. In the code he calls a heavy method 20 times to slow the game down. Instead of doing that, I want to check if the next frame should be handled.

The game is an object inside the template namespace. This namespace had an endless loop that calls the game tick method and swaps the frame buffers.

Inside this template, I replaced the Game->Tick() with a simple if statement:

if (game->Ready(lastftime)) {
    game->Tick();
}

lastframe is the time difference in in seconds between the last time it's called and now. I know I could use this time to calculate movements inside the game tick, but that's not what I want to do right now!

This is the Ready method:

bool Game::Ready(float timedif) {
    // Add time to framecounter
    framecounter += timedif;

    // Check if the counter over lapses the fps
    if (framecounter > fps) {
        // If so, substract the fps from the counter
        while (framecounter > fps) {
            framecounter -= fps;
        }
        m_Screen->Clear(0);
        Draw();

        return true;
    }

    // Frame is still inside the fps margin
    return false;
}

fps is calculated as follows: fps = 1000.0f/60

I have no idea why it doesn't run at 60 frames per second, and I'm 100% sure it's been called more than that (tested with a printf). Any help would be appreciated.


Solution

  • what is timedif?
    you should have some info about when in "real time" - for examples in ms was the last frame
    It seems to me that you assume that every iteration of ur while loop takes one ms.

    bool Game::Ready(float msSinceLastFrame)
    {
        if(msSinceLastFrame > fps)
        {
            m_Screen->Clear();
            Draw();
            return true;
        }       
        return false
    }
    
    //call this using some kind of while where you update msSinceLastFrame  
    if(game->Ready(msSinceLastFrame)
    {
        msSinceLastFrame = 0;
        game->Tick();
    }
    

    but, if you will use this approach you need to call game::ready loop using while();

    I Would suggest other approach.

    void Game::gameLoop()
    {
        auto lastFrameTimeStamp = GetTickCount(); // if you are on windows
        auto frameLength = 1000/fps;
        while(true) //true or some kind of condition
        {
            auto currentTimeStamp = GetTickCount();
            if( currentTimeStamp - lastFrameTimeStamp >= frameLength)
            {
                //do your job;
                lastFrameTimeStamp = currentTimeStamp;
            }
            Sleep(1); // you can use sleep here if you dont want to heat ur pcu =)
        }
    }