Agora que sabemos como carregar e exibir superfícies, vamos continuar nossa serie de artigos traduzido do site lazyfoo mostrando como tornar a exibição mais rápida. Também iremos usar uma imagem menor e estica-la para caber na tela.
Até agora, nós estávamos exibindo imagens brutas. Como estávamos exibindo apenas uma imagem, isso não importava. Quando estiver criando um jogo complexo, exibir imagens brutas causa lentidão desnecessária. Iremos agora ver como converter as imagens para um formato otimizado.
O SDL 2 possui também um novo recurso para superfícies chamado de soft stretching (alongamento suave), que permite que você exiba uma imagem escalonada em um tamanho diferente do original. Nesse artigo iremos usar uma imagem com metade do tamanho da tela estica-la para ocupar todo o espaço.
SDL_Surface* loadSurface( std::string path ) { //The final optimized image SDL_Surface* optimizedSurface = NULL; //Load image at specified path SDL_Surface* loadedSurface = SDL_LoadBMP( path.c_str() ); if( loadedSurface == NULL ) { printf( "Unable to load image %s! SDL Error: %s\n", path.c_str(), SDL_GetError() ); }
De volta à nossa função de carregamento de imagem, iremos fazer algumas modificações de forma que a superfície seja convertida ao ser carregada. No início da função carregamos as imagens basicamente da mesma forma que fazíamos nos artigos anteriores, mas também declaramos um ponteiro para a imagem otimizada.
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; }
Se a imagem for carregada com sucesso nas linhas anteriores do código, nós passamos para a otimização da superfície.
Veja bem, quando você carrega um bitmap, tipicamente ele é carregado em um formato de 24 bits, pois a maioria dos bitmaps possuem 24 bits. A maioria das telas não são 24 bits por padrão. Se exibirmos uma imagem de 24 bits em uma de 32 bits, o SDL irá converter essa imagem a toda vez que ela for exibida.
Assim, o que iremos fazer ao carregar uma imagem é converte-la para o mesmo formato da tela de forma que nenhuma conversão se faça necessária para exibi-la. Isso pode ser feito facilmente com a função SDL_ConvertSurface. Tudo que temos que fazer é informar junto com a superfície que queremos converter o formato da tela.
É importante observar que SDL_ConvertSurface retorna uma cópia da imagem original em um novo formato. A imagem original ainda fica na memória depois dessa chamada. Isso significa que temos que liberar a memória utilizada pela superfície original ou teremos duas cópias da mesma imagem na memória.
Depois que a imagem for carregada e convertida, nós retornamos a imagem otimizada final.
Para quem argumentar que o último argumento de SDL_ConvertSurface deve ser 0, NULL é 0. Se seu compilador mostrar um aviso, você pode mudar o último argumento para 0.
//Apply the image stretched SDL_Rect stretchRect; stretchRect.x = 0; stretchRect.y = 0; stretchRect.w = SCREEN_WIDTH; stretchRect.h = SCREEN_HEIGHT; SDL_BlitScaled( gStretchedSurface, NULL, gScreenSurface, &stretchRect );
O SDL 2 possui uma nova função dedicada a exibir imagens em um tamanho diferente: SDL_BlitScaled. Da mesma forma que exibimos imagens nos artigos anteriores, SDL_BlitScaled pega uma superfície original e exibe no destino. Também pode usar um destino SDL_Rect que define a posição e tamanho da imagem que você está exibindo.
Assim, se quisermos usar uma imagem que é menor do que a tela e exibir ela no mesmo tamanho da tela, você informa a mesma altura/largura tanto para o destino quanto para a tela.
Baixe os arquivos de imagem e o código fonte para esse artigo aqui.