(译)SDL编程入门(6)扩展库SDL_image

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

扩展库 SDL_image

SDL扩展库允许你做一些事情,比如加载BMP以外的图像文件,渲染TTF字体,以及播放音乐。您可以设置SDL_image来加载PNG文件,这可以为您节省大量的磁盘空间。在本教程中,我们将介绍如何安装SDL_image。

SDL本身是一个扩展库,因为它增加了游戏和媒体功能,而这些功能并不是你的C++编译器的标准配置。当你设置扩展库的时候,你会发现它和单独安装SDL几乎是一样的。我们将特别安装SDL_image,但如果你能安装该扩展库,你应该能够安装任何一个扩展库。

您需要做的第一件事是下载SDL_image头文件和二进制文件。您可以在SDL_image网站[1]上找到它们

在设置好SDL_image之后,我们将介绍如何使用SDL创建加载PNG。

现在库已经全部设置好了,让我们加载一些PNG。

//使用SDL、SDL_image、标准IO和字符串。
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>

要使用任何 SDL_image 函数或数据类型,我们需要包含 SDL_image 头。对于SDL_ttf,或者SDL_mixer,我们也要做同样的事情。

bool init(){
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL Error: %sn", 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: %sn", SDL_GetError() );
            success = false;
        }
        else
        {
            //初始化PNG加载
            int imgFlags = IMG_INIT_PNG;
            if( !( IMG_Init( imgFlags ) & imgFlags ) )
            {
                printf( "SDL_image could not initialize! SDL_image Error: %sn", IMG_GetError() );
                success = false;
            }
            else
            {
                //Get window surface
                gScreenSurface = SDL_GetWindowSurface( gWindow );
            }
        }
    }

    return success;
}

现在我们使用SDL_image,我们需要初始化它。这里我们想用PNG加载来初始化SDL_image,所以我们将PNG加载标志传递给IMG_Init。IMG_Init返回成功加载的标志。如果返回的标志不包含我们要求的标志,那就意味着出现了错误。

当SDL_image出现错误时,你会用IMG_GetError得到错误字符串,而不是SDL_GetError。

Also:STOP E-MAILING ME TELLING ME THAT THAT CALL TO IMG_Init IS A BUG!STOP E-MAILING ME TELLING ME THAT THAT CALL TO IMG_Init IS A BUG!STOP E-MAILING ME TELLING ME THAT THAT CALL TO IMG_Init IS A BUG!STOP E-MAILING ME TELLING ME THAT THAT CALL TO IMG_Init IS A BUG!STOP E-MAILING ME TELLING ME THAT THAT CALL TO IMG_Init IS A BUG!

不是的,IMG_INIT_PNG是2。如果你用IMG_INIT_PNG初始化,然后得到IMG_INIT_PNG,你得到的是2 & 2,也就是2。2会被评估为true, !否定它,这意味着它会被评估为false ,这将导致SDL_GetWindowSurface行执行。

如果你想从IMG_Init取回4,而你想要的是2,那么4 &2是0,它的值是false,这就被 ! 否定了,它的值是true,这将导致错误打印代码的执行。

如果当你想要2的时候,从IMG_Init中取回6(包括4和2位),6 & 2是2,它的值为true,被 !否定为false,这将导致SDL_GetWindowSurface一行执行。

代码之所以是这样,是因为我们只关心PNG加载位。如果我们得到了,就意味着我们可以继续。在其他情况下,这段代码会有所不同,但我们在这里不处理这个问题。

所以一定要把你的二进制数学学好,不要再发邮件告诉我说调用IMG_Init是个BUG!。说真的,我收到的错误报告中,有25%是这样的。

SDL_Surface* loadSurface( std::string path ){
    //The final optimized image
    SDL_Surface* optimizedSurface = NULL;

    //Load image at specified path
    SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
    if( loadedSurface == NULL )
    {
        printf( "Unable to load image %s! SDL_image Error: %sn", path.c_str(), IMG_GetError() );
    }
    else
    {
        //Convert surface to screen format
        optimizedSurface = SDL_ConvertSurface( loadedSurface, gScreenSurface->format, 0 );
        if( optimizedSurface == NULL )
        {
            printf( "Unable to optimize image %s! SDL Error: %sn", path.c_str(), SDL_GetError() );
        }

        //Get rid of old loaded surface
        SDL_FreeSurface( loadedSurface );
    }

    return optimizedSurface;
}

我们的图像加载功能和以前差不多,只是现在它使用IMG_Load而不是SDL_LoadBMP。IMG_Load 可以加载许多不同类型的格式,你可以在 SDL_image 文档[2]中找到相关信息。和IMG_Init一样,当IMG_Load出现错误时,我们调用IMG_GetError来获取错误字符串。

这里[3]下载本教程的媒体和源代码。

参考资料

[1]

SDL_image网站: https://www.libsdl.org/projects/SDL_image/

[2]

SDL_image 文档: https://www.libsdl.org/projects/SDL_image/docs/index.html

[3]

这里: http://www.lazyfoo.net/tutorials/SDL/06_extension_libraries_and_loading_other_image_formats/06_extension_libraries_and_loading_other_image_formats.zip

[4]

原文链接: http://www.lazyfoo.net/tutorials/SDL/06_extension_libraries_and_loading_other_image_formats/index2.php