开发者

What causes the stuttering framerate in this simple SDL rendering loop?

I wrote a very basic test to see if SDL would work properly on my system. I assumed it would run perfectly smoothly because the drawing code is very simple, but it is not smooth at all, and looks bad in different ways depending on the frame rate that I specify.

My hope is that I have done something silly. My worry is that the code is fine, but my Windows 7 machine won't play nicely with SDL. I've tinkered and googled excessively, but I can't figure out what's going on. Can someone more knowledgeable see a problem? The code is below:

#include "SDL.h"

static int g_width = 1024;
static int g_height = 768;

static int g_frameWaitInterval = 20;   // 50fps
static int g_lastFrameTime = 0;

static int g_ballx = 200;
static int g_bally = 200;
static int g_ballSize = 20;
static int g_ballxVelocity = 5;

void Step();
void Draw();

// Main application loop
void Run(){        
    while(true){
        if(SDL_GetTicks() - g_lastFrameTime >= g_frameWaitInterval){
            g_lastFrameTime = SDL_GetTicks();
            Step();
            Draw();
        }
    }
}

// Bounces the ball back and forth across the screen
void Step(){
    g_ballx += g_ballxVelocity;
    if(g_ballx+g_ballSize>=g_width){
        g_ballx = g_width - (g_ballSize+1);
        g_ballxVelocity = -g_ballxVelocity;
    }
    if(g_ballx<0){
        g_ballx = 0;
        g_ballxVelocity = -g_ballxVelocity;
    }
}

// Draws the ball as a square
void Draw(){
    SDL_Surface* p_screen = SDL_GetVideoSurface();
    SDL_FillRect(p_screen, NULL, 0xff000000);

    SDL_Rect rect;
    rect.x = g_ballx; rect.y = g_bally;
    rect.w = rect.h = g_ballSize;
    SDL_FillRect(SDL_GetVideoSurface(), &rect, 0xffff00ff);

    SDL_UpdateRect(p_screen,0,0,0,0);
}

// Initialises SDL, etc (checking removed for brevity)
int main(int argc, char *argv[]){
    SDL_Init(SDL_INIT_VIDEO);
    SDL_SetVideoMode(g_width, g_height, 0, SDL_SWSURFACE);
    Run();
    return 0;
}

Edit: I ran a framerate test over the course of 10 seconds and got 49.76, which is very close to the 50fps I was开发者_JAVA技巧 expecting. I also printed out a huge number of individual frame timings and found that every frame took 20ms, as expected. This suggests to me that the problem is with some aspect of the configuration, rather than my rendering loop.


You may just need to set up double buffering. Without it you can get a little bit of flickering, even on simple programs.


I think that the problem is that you are using a busy loop, and Windows probably throttles your process, or something like that.

Also, if you want the animation to run smoothly you should add g_frameWaitInterval to g_lastFrameTime, instead of updating it to the return of SDL_GetTicks(). Otherwise you may accumulate differences and make the animation uneven.

Try the following:

void Run(){        
    while(true){
        Uint32 now = SDL_GetTicks();
        Uint32 dif = now - g_lastFrameTime;

        if (now  >= g_lastFrameTime + g_frameWaitInterval){
            g_lastFrameTime += g_frameWaitInterval;
            Step();
            Draw();
            if (now  >= g_lastFrameTime + g_frameWaitInterval){
                //You are losing time! Correct it!
                g_lastFrameTime = now;
            }
        }
        else {
            //Play nice with CPU time
            SDL_Delay(g_frameWaitInterval - dif);
        }
    }
}


To get perfectly smooth sequences of images, you need to both set up double buffering (where you draw into one image, while another is shown on the screen, and swap them after your drawing procedure is done), and vsync, where you cap your frame rate to the refresh rate of your monitor, thus avoiding tearing effects. On modern systems, these two effects are the only probable factors I can think of that could result in choppy, flickery animation.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜