Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've written a simple class to limit the framerate of my current project. But it does not work as it should. Here is the code:

void FpsCounter::Process()
{
    deltaTime = static_cast<double>(frameTimer.GetMsecs());
    waitTime = 1000.0/fpsLimit - deltaTime;
    frameTimer.Reset();

    if(waitTime <= 0)
    {
        std::cout << "error, waittime: " << waitTime << std::endl;
    }
    else
    {
        SDL_Delay(static_cast<Uint32>(waitTime));
    }

    if(deltaTime == 0)
    {
        currFps = -1;
    }
    else
    {
        currFps = 1000/deltaTime;
    }

    std::cout << "--Timings--" << std::endl;
    std::cout << "Delta: \t" << deltaTime << std::endl;
    std::cout << "Delay: \t" << waitTime << std::endl;
    std::cout << "FPS: \t" << currFps << std::endl;
    std::cout << "--       --" << std::endl;
}

Timer::Timer()
{
    startMsecs = 0;
}

Timer::~Timer()
{
    // TODO Auto-generated destructor stub
}

void Timer::Start()
{
    started = true;
    paused = false;
    Reset();
}

void Timer::Pause()
{
    if(started && !paused)
    {
        paused = true;

        pausedMsecs = SDL_GetTicks() - startMsecs;
    }
}

void Timer::Resume()
{
    if(paused)
    {
        paused = false;

        startMsecs = SDL_GetTicks() - pausedMsecs;

        pausedMsecs = 0;
    }
}

int Timer::GetMsecs()
{
    if(started)
    {
        if(paused)
        {
            return pausedMsecs;
        }
        else
        {
            return SDL_GetTicks() - startMsecs;
        }
    }
    return 0;
}

void Timer::Reset()
{
    startMsecs = SDL_GetTicks();
}

The "FpsCounter::Process()" Method is called everytime at the end of my gameloop.

I've got the problem that the loop is correctly delayed only every second frame, so it runs one frame delayed at 60 FPS and the next without delay at over 1000 fps.

I am searching the error quite a while now, but I do not find it.

I hope somebody can point me in the right direction.

share|improve this question
    
What is the output from your cout calls when this happens? –  Kylotan Apr 14 '12 at 11:23
    
Just v-sync, everthing else does not make much sense for the game thread –  Maik Semder Apr 14 '12 at 18:23

4 Answers 4

up vote 1 down vote accepted

You need to reset the timer after you have waited. Otherwise, the wait time will be part of the duration of the next frame and the algorithm will think it is running slowly.

share|improve this answer

This problem have already been discussed here : Make the game run 60 fps in Irrlicht Engine

(initial question is for iirlicht engine but what have been said there also applied to other environments)

share|improve this answer
    
This should be a comment on the main question. –  Jonathan Hobbs Apr 15 '12 at 0:55

This wrong on many levels. The code behaves like it does because you reset the timer before you have finished waiting for the correct time for the current frame to come. If you moved the reset to after the wait block it should work like you have planned.

This is however still a very poor and inexact time control as it does not correct slight lapses of one frame in the next. What you really need is to have game logic running at a fixed rate and rendering running as fast as possible, though possibly with v-sync on so that it is limited to the screen update rate.

Your game loop should look something like this: (Edited, pausing will probably work better in the new version.)

double nextFrame = static_cast<double>SDL_GetTicks();
while(true){
    while(nextFrame > static_cast<double>SDL_GetTicks()){
        render();
    }
    nextFrame += 1000.0 / logicrate;
    if(!paused)
        gameLogic();
}

Alternate version that caps the frame rate at the logic rate:

double nextFrame = static_cast<double>SDL_GetTicks();
while(true){
    if(nextFrame > static_cast<double>SDL_GetTicks()){
        render();
    }
    if(!paused)
        gameLogic();
    delay = static_cast<Uint32> (nextFrame - static_cast<double>SDL_GetTicks());
    if(delay > 0){
        SDL_Delay(delay);
    }
    nextFrame += 1000.0 / logicrate;
}
share|improve this answer
    
I don't understand why it is bad to limit the framerate by wait a calculated time at the end of every loop. Can you explain that a little bit more? Also I have in mind to port my game to android, so I think sleeping a few microseconds where it is possible should be also positive for battery life. –  shad0w Apr 14 '12 at 14:29
1  
@shad0w: If you try to limit the frame rate to 60 fps, and you start taking longer than 1/60 s to render, then your frame rate will start to be divided by the number of frames it takes to render the scene: 30fps, 20fps, 15fps, and so on. Whereas, if you render/update based on how fast the game is actually running, the frame rate degrades much more gracefully. You do this by recording the time it takes to render the scene (dt), then advancing the scene by that amount, e.g., position += velocity * dt. –  Jon Purdy Apr 14 '12 at 15:09
    
I know that, but I think my game wont become so complex that it will take more time to render then 1/60 sec. At least I hope so. I also tried time based movement of, but that method ads a lots of complexity for me, so I would like to avoid that, as far as it is possible. –  shad0w Apr 14 '12 at 15:28
1  
You can never guarantee that your game wont run at less than 1/60th of a second, even on PCs that are faster than you require. Simply because a computer can do a lot of things while running the game, for example start the virus scanner or a backup procedure. These can cause notable stutter for a few seconds while your game is trying to catch up while one based on deltaTime never has to. –  Roy T. Apr 14 '12 at 16:54
    
Ok, I will consider that option. @eBusiness: Maybe I did not understand you correctly, but how does render more often than update makes senses? I think when the game doesn't get updated, there is nothing new to render. –  shad0w Apr 14 '12 at 17:08

Mine is something like this...

     timer.Update();

     static float frameTime = 0.0f;
     static int frames = 0;
     frameTime += timer.DeltaTime();
     frames++;

     while(frameTime >= kTimeStep)
     {
        (object->*callback)(frameTime);
        frames = 0;
        frameTime -= kTimeStep;
     }
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.