最近学习SDL2中用到了垂直同步这一技术,实现动画的处理,通过百科可知,垂直同步又称场同步,场信号一般是50Hz,或者60Hz,从CRT显示器的显示原理来看,单个像素组成了水平扫描线,水平扫描线在垂直方向的堆积形成了完整的画面,电脑中图象是通过显卡来显示的,比较高端的显卡生成图像更快些,垂直同步这一技术是让显卡生成图象时收到垂直同步信号的制约,使得画面更流畅些。如果没有垂直同步,图像速度就会提升,但是也会导致画面不流畅,出现跳帧现象,画面有撕裂现象,一般都是建议开启垂直同步,使得画面看起来狠舒适,
下面代码是加上垂直同步的代码
//Using SDL and standard IO
#include
#include
#include
#include
#include
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
#define NUMBER_CLIPS 16
bool init();
bool loadMedia();
void close();
SDL_Texture* loadTexture(char* path);
SDL_Window* gWindow = NULL;
SDL_Texture* gSpriteSheetTexture = NULL;
SDL_Renderer* gRenderer = NULL;
SDL_Rect gSpriteClips[NUMBER_CLIPS];
SDL_Rect* currRect = NULL;
bool init()
{
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
success = false;
}
else
{
int imgFlag = IMG_INIT_PNG;
gRenderer = SDL_CreateRenderer(gWindow,-1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
if(gRenderer == NULL)
{
printf("Renderer counld'nt be create SDLError:%s\n", SDL_GetError());
success = false;
}
if(!(IMG_Init(imgFlag) & imgFlag))
{
printf("SDL_image could not initialize! SDL_image Error:%s\n",IMG_GetError());
success = false;
}
}
}
return success;
}
bool loadMedia()
{
bool success = true;
char i,j;
//Load splash image
gSpriteSheetTexture = loadTexture("walk.png");
if(gSpriteSheetTexture == NULL)
{
printf("Unable to load default image %s! SDL Error:%s\n","walk.png",SDL_GetError());
success = false;
}
else
{
for(i = 0; i < 4;i++)
{
for(j = 0; j < 4; j++)
{
gSpriteClips[4*i+j].x = 32*j;
gSpriteClips[4*i+j].y = 48*i;
gSpriteClips[4*i+j].w = 32;
gSpriteClips[4*i+j].h = 48;
}
}
}
return success;
}
SDL_Texture* loadTexture(char * path)
{
SDL_Texture* texture = NULL;
SDL_Surface* loadedSurface = IMG_Load(path);
if(loadedSurface == NULL)
{
printf("Unable to load image %s! SDL Error:%s\n",path,IMG_GetError());
}
else
{
texture = SDL_CreateTextureFromSurface(gRenderer,loadedSurface);
if(texture == NULL)
{
printf("Unable to optimize image %s!, SDL Error %s\n",path, SDL_GetError());
}
SDL_FreeSurface(loadedSurface);
}
return texture;
}
void close()
{
SDL_DestroyTexture(gSpriteSheetTexture);
gSpriteSheetTexture = NULL;
SDL_DestroyRenderer(gRenderer);
gRenderer = NULL;
SDL_DestroyWindow(gWindow);
gWindow = NULL;
IMG_Quit();
SDL_Quit();
}
int main( int argc, char* args[] )
{
int frame = 0;
if(!init())
{
printf("Failed to Initialized!\n");
}
else
{
if(!loadMedia())
{
printf("Failed to load image!\n");
}
else
{
bool quit = false;
SDL_Event e;
SDL_Rect distRect = {SCREEN_WIDTH/2 - 16, SCREEN_HEIGHT/2 - 24, 32,48};
while(!quit)
{
while(SDL_PollEvent(&e) != 0)
{
if(e.type == SDL_QUIT)
{
quit = true;
}
}
SDL_SetRenderDrawColor(gRenderer,0xff,0xff,0xff,0xff);
SDL_RenderClear(gRenderer);
currRect = &gSpriteClips[frame/8];
SDL_RenderCopy(gRenderer, gSpriteSheetTexture,currRect,&distRect);
SDL_RenderPresent(gRenderer);
frame++;
if(frame/8 >= NUMBER_CLIPS)
{
frame = 0;
}
}
}
}
close();
return 0;
}
画面比较流畅,当我们去掉创建渲染器的SDL_RENDERER_PRESENTVSYNC标志时,即
gRenderer = SDL_CreateRenderer(gWindow,-1, SDL_RENDERER_ACCELERATED);
明显可以看出,后者速率很快,但是运行轨迹没有前者流畅,我的监视器刷新频率是60Hz,gif动画的录制时间间隔是30ms,虽然不晓得 SDL_RenderPresent(SDL_Renderer* renderer)具体是怎么实现的,我想刷新时可能会在里面等待垂直同步信号到来吧。而且SDL_Renderer这个结构体看不到也。。。
参考链接:http://lazyfoo.net/tutorials/SDL/14_animated_sprites_and_vsync/index.php