Tutorial de SDL – Parte 53 – Extensões e mudança da orientação da tela

Continuando nossa série de artigos traduzidos do site lazyfoo, veremos agora como lidar com a orientação da tela em dispositivos móveis (retrato/paisagem).

No artigo anterior, vimos como configurar a biblioteca SDL2 e agora vamos precisar adicionar algumas bibliotecas de extensão do SDL. Felizmente, SDL_image/SDL_ttf/SDL_mixer são apenas outras bibliotecas que você precisa adicionar e se você já configurou SDL2, você já fez a parte díficil.

Configurando o SDL_image com o Android Studio no Linux

1) Primeiro, baixe o código fonte de SDL_image nessa página.

Extraia o c´ódigo fonte para o diretório “~/androidlib/SDL2_image-2.0.2”

2) Baixe o arquivo e assets de demonstração. Copie o diretório de dentro do arquivo para “~/androidprojects/SDL_Tutorial/app/src/main/assets”. Lembrete: se a aplicação precisa carregar “53_extensions_and_changing_orientation/portrait.png” precisa estar no diretório “~/androidprojects/SDL_Tutorial/app/src/main/assets/53_extensions_and_changing_orientation/portrait.png” quando for compilar.

3) Copie os arquivos de demonstração para “~/androidprojects/SDL_Tutorial/app/src/main/jni/src/53_extensions_and_changing_orientation.cpp”. Abra o arquivo de Makefile do jogo em “~/androidprojects/SDL_Tutorial/app/src/main/jni/src/Android.mk” e altere o local dos arquivos de código de fonte para incluir o novo arquivo de demonstração:

LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \
53_extensions_and_changing_orientation.cpp

Abra o Android Studio e tente compilar o projeto. Você verá um erro:

fatal error: ‘SDL_image.h’ file not found

Esse erro significa que nosso arquivo de código fonte não consegue encontrar o cabeçalho SDL_image.h pois não configuramos isso ainda.

4) SDL_image é apenas uma outra biblioteca compartilhada que precisamoscompilar junto com SDL2 e o código de nossa aplicação. Isso significa que precisamos criar um link simbólico para o código fonte de SDL_image. Vá para o diretório JNI dentro do diretório do projeto usando o comando:

cd ~/androidprojects/SDL_Tutorial/app/src/main/jni

E crie um link simbólico para o diretório do código fonte do SDL2_image que extraimos (LEMBRETE: Esse caminho irá variar dependendo de sua versão do SDL_image):

ln -s ~/androidlib/SDL2_image-2.0.2 SDL2_image

Tente compilar novamente, para visualizar o novo erro, mas ao menos você verá um link para SDL2_image no projeto agora.

5) Pode haver um link simbólico para SDL_image no diretório JNI mas nossa aplicação não sabe onde está. Para corrigir esse erro, abra o arquivo “~/androidprojects/SDL_Tutorial/app/src/main/jni/src/Android.mk” e altere

LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include

para

LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include $(LOCAL_PATH)/../SDL2_image/

Para que agora nossa aplicação possa encontrar os cabeçalhos do SDL_iamge. Tente compilar novamente para visualizar o novo erro:

Error:(120) undefined reference to `IMG_Load’
Error:(432) undefined reference to `IMG_Init’
Error:(477) undefined reference to `IMG_Quit’

6) Esses novos erros são erros de lincagem. Enquando SDL_image é compilada sem erros assim como nossa aplicação, não informamos ao NDK para lincar nossa aplicação com o SDL_Image. Em “~/androidprojects/SDL_Tutorial/app/src/main/jni/src/Android.mk” altere

LOCAL_SHARED_LIBRARIES := SDL2

para

LOCAL_SHARED_LIBRARIES := SDL2 SDL2_image

Tente compilar novamente. Você pode conseguir finalmente compilar a aplicação, mas pode encontrar um novo erro.

7) Você pode obter um erro No rule to make target para IMG_WIC.c. Esse erro é a bibliotecas webp sendo díficil de lidar. Só vamos remover ela da equação. Abra “~/androidlib/SDL2_image-2.0.2/Android.mk” e altere:

SUPPORT_WEBP ?= true

para

SUPPORT_WEBP ?= false

Apague a linha que contém

IMG_WIC.c \

e só apague o diretório  “~/androidlib/SDL2_image-2.0.2/external/libwebp-0.6.0”.

Tente compilar novamente e agora você não deve ver nenhum erro.

8) A aplicação deve ser compilada sem erros, mas AINDA NÃO VAI FUNCIONAR. Precisamos fazer com que nossa Activity Jaba carregar a biblioteca de extensão do SDL Abra “~/androidprojects/SDL_Tutorial/app/src/main/java/org/libsdl/app/SDLActivity.java” e procure a seção:

protected String[] getLibraries() {
return new String[] {
“SDL2”,
// “SDL2_image”,
// “SDL2_mixer”,
// “SDL2_net”,
// “SDL2_ttf”,
“main”
};
}
Descomente a linha com a bibliotecas que você quer se seja carregada.

9) Compile e execute a aplicação. A aplicação deve ser executada e girar quando a tela for giradea. Agora que a aplicação foi compilada, vamos explicar o código fonte.

Extensões e mudança de orientação da tela: Lidando com mudanças de orientação

Agora que temos SDl_image carregando PNGs, é o momento de lidar com o dispositivo girando a tela.

//Screen dimensions
SDL_Rect gScreenRect = { 0, 0, 320, 240 };
//Scene textures
LTexture gPortraitTexture;
LTexture gLandscapeTexture;

Para essa aplicação teremos um render diferente para as texturas dependendo se o dispositivo estiver em modo retrato ou paisagem.

                //Handle events on queue
                while( SDL_PollEvent( &e ) != 0 )
                {
                    //User requests quit
                    if( e.type == SDL_QUIT )
                    {
                        quit = true;
                    }
                    //Window event
                    else if( e.type == SDL_WINDOWEVENT )
                    {
                        //Window resize/orientation change
                        if( e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED )
                        {
                            //Get screen dimensions
                            gScreenRect.w = e.window.data1;
                            gScreenRect.h = e.window.data2;
                            //Update screen
                            SDL_RenderPresent( gRenderer );
                        }
                    }
                }

O SDL2 torna eventos de alteração de orientação em eventos de alteração de janela. Verificamos eventos de janela e se o evento for alteração do tamalho, obtemos as novas dimensões, e atualizamos a janela.

                //Clear screen
                SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
                SDL_RenderClear( gRenderer );
                //Render splash
                if( gScreenRect.h >= gScreenRect.w )
                {
                    gPortraitTexture.render( ( gScreenRect.w - gPortraitTexture.getWidth() ) / 2, ( gScreenRect.h - gPortraitTexture.getHeight() ) / 2 );
                }
                else
                {
                    gLandscapeTexture.render( ( gScreenRect.w - gLandscapeTexture.getWidth() ) / 2, ( gScreenRect.h - gLandscapeTexture.getHeight() ) / 2 );
                }
                //Update screen
                SDL_RenderPresent( gRenderer );

Como sabemos se o dispositivo está em modo retrato ou paisagem? Simples: se a altrua for maior que largura, estamos no modo retrato. Caso contrário, estamos no modo paisagem.

Baixe os arquivo de mídia e do código fonte desse artigo aqui.