Tutorial SDL – Parte 6 – Bibliotecas extras e Carregamento de outros formatos de imagem

Nesse artigo, continuando nossa série de artigos traduzido do site lazyfoo, iremos usar a biblioteca SDL_Image para carregar imagens PNG.

A bibliotecas de extras do SDL permitem que você faça coisas como carregar arquivos de imagem além do BMP, renderize fontes TTF, e toque música. Você pode configurar SDL_image para carregar arquivos de imagem PNG, o que pode economizar um bocado de espaço em disco. Nesse tutorial, iremos ver como instalar e usar a biblioteca SDL_image.

A própria SDL por si só é uma biblioteca extra já que ela adiciona funcionalidades para jogos e manipulação de arquivos de mídia que não vem por padrão com o compilador C++. Ao configurar a biblioteca extra, você verá que o procedimento é idêntico à instalação do SDL. Nós estaremos instalando especificamente SDL_image, mas se você conseguir instalar essa biblioteca é capaz de instalar qualquer uma delas.

Configurando as biblotecas extras do SDL

Windows

1) A primeira coisa que precisamos fazer é baixar os arquivo de cabeçalho e binários de SDL_image. Você poderá encontra-los no website do SDL_image, nesta página.

Você deve baixar a biblioteca de desenvolvimento do MinGW:

mingw_package

Abra o arquivo gzip e deve haver um arquivo tar dentro dele. Abra esse arquivo tar e deve haver uma pasta chamada SDL2_image-2.something.something. Dentro desta pasta deve existir vários arquivos e pastas, sendo as mais importantes i686-w64-mingw32 que contém a versão 32 bits a biblioteca e x86_64-w64-mingw32 que contém a versão de 64 bits.

2) Isso é importante: A maioria dos compiladores ainda gera binários de 32 bits para maximizar a compatibilidade. Usaremos os binários de 32 bits nesse tutorial. Não importa se você possuir um sistema operacional de 64 bits, já que criaremos arquivos binários de 32 bits iremos usar a biblioteca de 32 bits.

Dentro desse diretório estarão diretórios includelibbin que contém tudo que você precisa para compilar e executar aplicações SDL. Copie cada um desses diretórios para o local que você quiser. Eu recomendo por esses diretórios no local onde você instalou as bibliotecas de desenvolvimento do MinGW.

3) Agora iremos baixar o código do exemplo desse artigo. Agora baixe o código fonte do exemplo desse artigo. Descompacte o código em algum lugar, Abra uma janela de terminal nesse diretório clicando com o botão direito enquanto segura SHIFT e digite o comando abaixo (esse comando assume que você colocou SDL_image no diretório do MinGW):

g++ 06_extension_libraries_and_loading_other_image_formats.cpp -IC:\mingw_dev_lib\include\SDL2 -LC:\mingw_dev_lib\lib -w -Wl,-subsystem,windows -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -o 06_extension_libraries_and_loading_other_image_formats

Se estiver usando um Makefile, pode apenas alterar os valores de algumas macros:

Makefile

#OBJS specifies which files to compile as part of the project
OBJS = 06_extension_libraries_and_loading_other_image_formats.cpp

#CC specifies which compiler we're using
CC = g++

#INCLUDE_PATHS specifies the additional include paths we'll need
INCLUDE_PATHS = -IC:\mingw_dev_lib\include\SDL2

#LIBRARY_PATHS specifies the additional library paths we'll need
LIBRARY_PATHS = -LC:\mingw_dev_lib\lib

#COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
# -Wl,-subsystem,windows gets rid of the console window
COMPILER_FLAGS = -w -Wl,-subsystem,windows

#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lmingw32 -lSDL2main -lSDL2 -lSDL2_image

#OBJ_NAME specifies the name of our exectuable
OBJ_NAME = 06_extension_libraries_and_loading_other_image_formats

#This is the target that compiles our executable
all : $(OBJS)
	$(CC) $(OBJS) $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)

Como você pode ver é bem fácil alterar o nome do arquivo do código fonte e do executável e adicionar:
-lSDL2_image

ao linker. Se estivermos usando SDL_ttf, adicionamos:
-lSDL2_ttf

e para usar SDL_mixer:
-lSDL2_mixer

Linux

Na era dos gerenciadores de pacotes, um bocado de trabalho é feito para você ao instalar bibliotecas. Você precisará de privilégios de administrador para instalar o pacotes então certifique-se de usar “su” ou “sudo” se não estiver logado como root.

Certifique que você tenha atualizado para a versão mais recente de sua distribuição pois seu gerenciador de pacote antigo pode não suportar a versão mais recente do SDL_image/SDL_ttf/SDL_mixer.

1) Para aqueles que possuem o Advanced Packaging Tool (como Ubuntu e Debian) você terá que pesquisar com o comando apt-get cache para encontrar a versão do SDL_image a ser instalada. Você pode pesquisar pelos pacotes disponíveis com o comando:
apt-cache search libsdl2-image

Você irá precisar baixar a versão de desenvolvimento do SDL_image. Quando este artigo foi escrito, a versão de desenvolvimento do SDL 2 é a libsdl2-image-dev. Você pode baixar esse pacote usando o comando:
apt-get install libsdl2-image-dev

Para o SDL_ttf, o nome do pacote de desenvolvimento é o libsdl2-ttf-dev. Para SDL_mixer é o libsdl2-mixer-dev.

2) Se você estiver usando o Yellow dog Updater Modified (usado no Fedora e CentOS) pode usar o seguinte comando:
yum search SDL2_image-devel

Para procurar pelo pacote de desenvolvimento do SDL_image. Quando esse artigo foi escrito, esse pacote era o SDL2_image-devel. Você pode instalar esse pacote com o comando:
yum install SDL2_image-devel

para o SDL_ttf, o nome do pacote de desenvolvimento é o SDL2_ttf-devel. Para o SDL_mixer é SDL2_mixer-devel.

3) Se de alguma forma você não possuir um gerenciador de pacote, pode instalar compilando o código fontes da forma clássica do Unix. Baixe a última versão do código fontes no website do SDL.

download-linux

Extraia o arquivo e entre no diretório que você extraiu. Configure a instalação usando o comando:
./configure

Compile o código fonte usando o seguinte comando do make:
make all

Finalmente, instale o pacote usando o seguinte comando do make:
make install

4) Agora quer você instalou os arquivos da biblioteca, é hora de abrir seu IDE/Compilador favorito.

MacOSX

1) A primeira coisa que precisa ser feito é baixar os arquivos de desenvolvimento para o OS X no website do SDL.

download

2) Em seguida abra o arquivo DMG e copie o SDL2_image.framework para o diretório /Library/Frameworks. Para ir diretamente ao caminho no Finder, pressione command+shift+g.

copy_framework

3) O framework pode precisar ser reassinado. Para fazer isso, abra uma janela de terminal no diretório:
/Library/Frameworks/SDL2_image.framework/

e assine o framework com o comando:
codesign -f -s - SDL2_image

Se estiver reassinando o SDL_ttf, abra o terminal em:
/Library/Frameworks/SDL2_ttf.framework/

E assine o SDL_ttf usando o comando:
codesign -f -s - SDL2_ttf

Se estiver reassinando o SDL_mixer, abra o terminal em:
/Library/Frameworks/SDL2_mixer.framework/

E assine o SDL_mixer usando o comando:
codesign -f -s - SDL2_mixer

4) Agora quer você instalou os arquivos da biblioteca, é hora de abrir seu IDE/Compilador favorito.

Carregando imagens PNG com SDL_image

Agora que a biblioteca foi configurada, vamos carregar alguns arquivos PNG.

//Using SDL, SDL_image, standard IO, and strings
#include
#include
#include
#include

Para usar qualquer função ou tipo de dados do SDL_image, precisamos incluir  cabeçalho do SDL_image. Temos que fazer o mesmo se formos usar SDL_ttf e 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: %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
        {
            //Initialize PNG loading
            int imgFlags = IMG_INIT_PNG;
            if( !( IMG_Init( imgFlags ) & imgFlags ) )
            {
                printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
                success = false;
            }
            else
            {
                //Get window surface
                gScreenSurface = SDL_GetWindowSurface( gWindow );
            }
        }
    }

    return success;
}

Agora que estamos usando SDL_image, precisamos inicializa-la. Aqui vamos inicializar SDL_image com o recurso de carregamento de arquivos PNG, assim nós adicionamos as flags de carregamento de PNH em IMG_Init. IMG_Init retornas as flags que foram carregadas com sucesso.  Se as flags que forem retornadas não forem as mesma que foram requisitadas, isso significa que houve um erro.

Quando um ocorre ocorre com SDL_image, você tem acesso à string de erro com IMG_GetError ao invés de SDL_GetError.

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: %s\n", path.c_str(), IMG_GetError() );
    }
    else
    {
        //Convert surface to screen format
        optimizedSurface = SDL_ConvertSurface( loadedSurface, gScreenSurface->format, NULL );
        if( optimizedSurface == NULL )
        {
            printf( "Unable to optimize image %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
        }

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

    return optimizedSurface;
}

Nossa função de carregamento de imagem é basicamente a mesma de antes, só que agora usa IMG_Load ao invés de SDL_LoadBMP. IMG_Load pode carregar diferentes tipos de formatos de imagem que você pode saber quais na documentação de SDL_image. Como no caso de IMG_Init, quando ocorre um erro com IMG_Load, chamamos IMG_GetError para obter a string do erro.

Baixe o arquivo de imagem e o código fonte desse artigo aqui.