动画简而言之就是展示一个又一个的图像来制造运动的假象。在这里我们将展示不同的精灵来制作一个简笔画的动画。
假设我们有以下动画帧(这清楚地表明我不是动画师):
而且每隔十分之一秒就显示一个,我们会得到这个动画:
由于SDL 2中的图像是典型的SDL_Textures,所以在SDL中的动画是一个接一个地显示纹理的不同部分(或不同的整体纹理)。
//走路动画
const int WALKING_ANIMATION_FRAMES = 4;
SDL_Rect gSpriteClips[ WALKING_ANIMATION_FRAMES ];
LTexture gSpriteSheetTexture;
所以,这里我们有带有精灵的精灵表,我们要用它来制作动画。
//为窗口创建垂直同步渲染器
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
对于本篇(以及未来的教程),我们要使用垂直同步。VSync允许渲染在垂直刷新期间与你的显示器更新时同步更新。对于本教程,它将确保动画不会运行得太快。大多数显示器以每秒60帧左右的速度运行,这是我们在这里做的假设。如果你有一个不同的显示器刷新率,这将解释为什么动画运行太快或太慢。
bool loadMedia(){
//Loading success flag
bool success = true;
//Load sprite sheet texture
if( !gSpriteSheetTexture.loadFromFile( "14_animated_sprites_and_vsync/foo.png" ) )
{
printf( "Failed to load walking animation texture!\n" );
success = false;
}
else
{
//Set sprite clips
gSpriteClips[ 0 ].x = 0;
gSpriteClips[ 0 ].y = 0;
gSpriteClips[ 0 ].w = 64;
gSpriteClips[ 0 ].h = 205;
gSpriteClips[ 1 ].x = 64;
gSpriteClips[ 1 ].y = 0;
gSpriteClips[ 1 ].w = 64;
gSpriteClips[ 1 ].h = 205;
gSpriteClips[ 2 ].x = 128;
gSpriteClips[ 2 ].y = 0;
gSpriteClips[ 2 ].w = 64;
gSpriteClips[ 2 ].h = 205;
gSpriteClips[ 3 ].x = 196;
gSpriteClips[ 3 ].y = 0;
gSpriteClips[ 3 ].w = 64;
gSpriteClips[ 3 ].h = 205;
}
return success;
}
在加载完精灵表后,我们要定义各个动画帧的精灵。
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//Current animation frame
int frame = 0;
在主循环之前,我们必须声明一个变量来跟踪当前的动画帧。
//渲染当前帧
SDL_Rect* currentClip = &gSpriteClips[ frame / 4 ];
gSpriteSheetTexture.render( ( SCREEN_WIDTH - currentClip->w ) / 2, ( SCREEN_HEIGHT - currentClip->h ) / 2, currentClip );
//Update screen
SDL_RenderPresent( gRenderer );
在主循环中清空屏幕后,我们要渲染当前帧的动画。
动画从第0帧到第3帧,由于动画只有4帧,所以我们要把动画的速度放慢一点。这就是为什么当我们得到当前裁剪精灵时,我们要将帧除以4。这样实际的动画帧只每4帧更新一次,因为用int数据类型0/4=0,1/4=0,2/4=0,3/4=0,4/4=1,5/4=1,等等。
当我们得到当前的精灵后,我们要把它渲染到屏幕上,并更新屏幕。
//转到下一帧
++frame;
//循环动画
if( frame / 4 >= WALKING_ANIMATION_FRAMES )
{
frame = 0;
}
}
现在为了让帧更新,我们需要每一帧递增帧值。如果我们不这样做,那么动画将停留在第一帧。
我们还想让动画循环,所以当帧达到最终值(16 / 4 = 4)时,我们将帧重置为0,这样动画就会重新开始。
在我们通过递增或循环更新帧到0之后,我们就到达了主循环的终点。这个主循环将不断地显示一帧并更新动画值,使精灵产生动画。
[1]
这里: http://www.lazyfoo.net/tutorials/SDL/14_animated_sprites_and_vsync/14_animated_sprites_and_vsync.zip
[2]
原文链接: http://www.lazyfoo.net/tutorials/SDL/14_animated_sprites_and_vsync/index.php