(译)SDL编程入门(14)动画精灵和VSync

时间:2022-07-27
本文章向大家介绍(译)SDL编程入门(14)动画精灵和VSync,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

动画精灵和VSync

动画简而言之就是展示一个又一个的图像来制造运动的假象。在这里我们将展示不同的精灵来制作一个简笔画的动画。

假设我们有以下动画帧(这清楚地表明我不是动画师):

而且每隔十分之一秒就显示一个,我们会得到这个动画:

由于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: %sn", 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