Что вызывает заикание частоты кадров в этом простом цикле рендеринга SDL? - PullRequest
2 голосов
/ 15 октября 2011

Я написал очень простой тест, чтобы проверить, будет ли SDL нормально работать в моей системе.Я предположил, что он будет работать идеально гладко, потому что код рисования очень прост, но он совсем не гладкий, и выглядит плохо по-разному, в зависимости от указанной частоты кадров.

Я надеюсь, что у меня естьсделал что-то глупое.Меня беспокоит то, что код в порядке, но мой компьютер с Windows 7 не будет хорошо работать с SDL.Я много возился и гуглил, но не могу понять, что происходит.Может ли кто-то более знающий увидеть проблему?Код ниже:

#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;
}

Редактировать: Я выполнил тест частоты кадров в течение 10 секунд и получил 49,76, что очень близко к 50 к / с, которые я ожидал.Я также распечатал огромное количество отдельных кадров и обнаружил, что каждый кадр занимает 20 мс, как и ожидалось.Это наводит меня на мысль, что проблема в каком-то аспекте конфигурации, а не в моем цикле рендеринга.

Ответы [ 3 ]

1 голос
/ 15 октября 2011

Я думаю, что проблема в том, что вы используете занятый цикл, и Windows, вероятно, душит ваш процесс или что-то в этом роде.

Кроме того, если вы хотите, чтобы анимация работала плавно, вы должны добавить g_frameWaitInterval в g_lastFrameTime, вместо обновления до возврата SDL_GetTicks ().В противном случае вы можете накапливать различия и делать анимацию неравномерной.

Попробуйте выполнить следующее:

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);
        }
    }
}
1 голос
/ 15 октября 2011

Чтобы получить идеально гладкие последовательности изображений, вам нужно настроить двойную буферизацию (когда вы рисуете одно изображение, в то время как другое отображается на экране, и поменять их местами после завершения процедуры рисования), и vsync, где Вы ограничиваете частоту кадров до частоты обновления вашего монитора, таким образом избегая эффект слезотечения. В современных системах эти два эффекта являются единственными вероятными факторами, о которых я могу думать, что может привести к прерывистой, мерцающей анимации.

1 голос
/ 15 октября 2011

Возможно, вам просто нужно настроить двойную буферизацию.Без этого вы можете слегка мерцать даже на простых программах.

...