Ciclo de aula do SDL 2.0: Lição 3 - Bibliotecas de extensão SDL

SDL2

Do tradutor:

Continuo a série abandonada de traduções de tutoriais da Twinklebear, originalmente disponíveis aqui , com a permissão do tradutor das lições anteriores da série InvalidPointer . As duas primeiras lições de uma série de traduções da lista são de autoria dele. A tradução é parcialmente gratuita e pode conter pequenas alterações ou acréscimos do tradutor.

Lista de lições:


Bibliotecas de extensão SDL


Até aquele momento, usamos apenas imagens BMP, pois esse é o único tipo de imagem suportado pela biblioteca principal do SDL 2 e não é muito conveniente. Felizmente, existem muitas bibliotecas de extensão SDL que adicionam recursos úteis, por exemplo, SDL_image permite carregar muitos tipos de imagens, SDL_ttf adiciona suporte para renderização de texto usando fontes TTF, SDL_net para suporte de rede de baixo nível e SDL_mixer para saída de áudio multicanal.

Instalar extensão


Neste tutorial, usaremos apenas SDL_image, no entanto, o processo de instalação para as outras extensões não é diferente e, em geral, quase coincide com o da instalação do SDL2.

  • Windows (MinGW ou Visual Studio): Coloque os arquivos de extensão baixados da página do projeto de extensão em uma pasta com SDL2. Além disso, você precisa copiar SDL2_image, zlib e outros arquivos .dll (por exemplo, libpng) para a pasta com seu arquivo executável (ou em C: \ Windows \ system32 - aprox. Por. ) Para que eles sejam carregados quando o aplicativo for iniciado.
  • Linux : instale a extensão usando o gerenciador de pacotes interno ou crie a partir da fonte. Se você possui Linux - provavelmente já sabe como fazê-lo ©.
  • Mac : faça o download do arquivo .dmg no site oficial e siga as instruções no Leia-me.

Além disso, para usar a extensão, você precisará atualizar a lista de arquivos de cabeçalho e bibliotecas de plug-ins usados, exatamente como foi feito para o próprio SDL2.

Antes de começar a trabalhar com a extensão, é necessário conectar o arquivo <SDL2 / SDL_image.h> ou o arquivo correspondente ao nome da extensão desejada, após o arquivo de cabeçalho do próprio SDL aos arquivos .c e .cpp usando-o.

Inicializando SDL_image (opcional)


No primeiro carregamento da imagem de cada tipo, SDL_image inicializa automaticamente o subsistema necessário para esse tipo; no entanto, isso causa um pequeno atraso. Para evitar isso, você pode pré-inicializar os subsistemas necessários usando a função IMG_Init. IMG_Init retorna uma máscara de bits com uma lista de todos os subsistemas que foram inicializados com sucesso no momento. Portanto, para verificar o sucesso da chamada, é necessário verificar se os bits de todos os subsistemas indicados para inicialização foram definidos, por exemplo, aplicando uma máscara ao resultado I. bit a bit. Para esta lição, precisamos apenas de um subsistema. PNG. É importante executar esta operação após SDL_Init.

if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG) { logSDLError(std::cout, "IMG_Init"); SDL_Quit(); return 1; } 


Definir dimensões


Nesta lição, veremos como carregar imagens usando SDL_image, como dimensionar texturas ao renderizar e ladrilhar o fundo com ladrilhos de maneira mais racional do que na lição anterior - um ciclo baseado nos tamanhos das janelas e dos ladrilhos.

Mas primeiro, vamos definir uma constante para o tamanho do bloco, logo abaixo das constantes para o tamanho da janela.

 const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; //     const int TILE_SIZE = 40; 

Upload de imagens usando SDL_image


SDL_image permite carregar vários tipos de imagens, bem como convertê-las imediatamente em SDL_Texture com a função IMG_LoadTexture. Esta função substitui quase todo o código da função loadTexture da lição anterior, agora chame IMG_LoadTexture, verifique se houve algum erro durante o carregamento e saia da função. Como a função IMG_GetError definida em SDL_image nada mais é do que um sinônimo para SDL_GetError, podemos usar qualquer um deles para exibir mensagens de erro.

 /** *       * @param file    * @param ren ,        * @return  ,  nullptr   . */ SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren) { SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str()); if (!texture) { std::cout << IMG_GetError(); //    SDL_GetError() } return texture; } 

Especifique a altura e a largura para renderização


Se você especificar um tamanho de retângulo diferente do tamanho da textura ao renderizar a textura para o renderizador, o SDL2 a escalará de acordo. No entanto, se a escala não for necessária, pode ser inconveniente determinar o tamanho inicial da textura a cada vez; portanto, implementaremos duas versões da função renderTexture, uma das quais desenhará a textura com escala e a segunda sem.

 /** *  SDL_Texture  SDL_Renderer   x, y,   * @param tex    * @param ren  * @param x  * @param y * @param w     * @param h */ void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, int w, int h) { SDL_Rect dst; dst.x = x; dst.y = y; dst.w = w; dst.h = h; SDL_RenderCopy(ren, tex, NULL, &dst); } /** *  SDL_Texture  SDL_Renderer   x, y,   * @param tex  * @param ren  * @param x  * @param y */ void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y) { int w, h; SDL_QueryTexture(tex, NULL, NULL, &w, &h); renderTexture(tex, ren, x, y, w, h); } 

Carregando texturas


Como o principal objetivo desta lição é fazer o download de imagens PNG, usaremos um novo conjunto de imagens. Além disso, demonstraremos a preservação da transparência PNG ao renderizar uma imagem em primeiro plano (com fundo transparente) sobre um fundo lado a lado.

Usaremos estas imagens:

Lado a lado para preencher o plano de fundo:



Imagem do primeiro plano (como está escrito, com um fundo transparente e também com emoticons que violam as regras de Habr):



Upload de imagens:

 SDL_Texture *background = loadTexture("background.png", renderer); SDL_Texture *image = loadTexture("image.png", renderer); //  if (!background || !image) { //  ,      cleanup(),   PS   ,     ,  ,    . SDL_DestroyTexture(background); SDL_DestroyTexture(image); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); IMG_Quit(); SDL_Quit(); return 1; } 

Fundo de azulejos


Como os ladrilhos são visivelmente menores, precisaremos colocar mais de quatro peças para preencher a janela inteira e será muito difícil especificar a posição de cada uma manualmente. Felizmente, você pode fazer com que o computador determine essas posições sozinho.

Podemos descobrir quantos ladrilhos são necessários em largura, dividindo a largura da janela pelo tamanho do ladrilho e da mesma forma para a altura.

 //   ,      //  :     ceil(float(SCREEN_WIDTH) / TILE_SIZE),    ,       ,      ; ,        ,     . int xTiles = SCREEN_WIDTH / TILE_SIZE; int yTiles = SCREEN_HEIGHT / TILE_SIZE; //   for (int i = 0; i < xTiles * yTiles; ++i) { int x = i % xTiles; int y = i / xTiles; renderTexture(background, renderer, x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE); } 

Desenho de imagem em primeiro plano


Como antes, a imagem em primeiro plano é colocada no meio da janela.

 int iW, iH; SDL_QueryTexture(image, NULL, NULL, &iW, &iH); int x = SCREEN_WIDTH / 2 - iW / 2; int y = SCREEN_HEIGHT / 2 - iH / 2; renderTexture(image, renderer, x, y); 

Resta apenas exibir o resultado na janela e aguardar alguns segundos, como na segunda lição.

 SDL_RenderPresent(renderer); SDL_Delay(2000); 

Limpeza


A liberação de recursos é semelhante à da lição 2 (e já foi vista acima ao processar um erro ao carregar uma imagem), exceto pela chamada adicionada IMG_Quit.

 SDL_DestroyTexture(background); SDL_DestroyTexture(image); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); IMG_Quit(); SDL_Quit(); 

Após a compilação e o lançamento bem-sucedidos, se você fez tudo corretamente, a janela será mais ou menos assim:



O fim da terceira lição


Então, a próxima lição chegou ao fim. Vejo você na lição 4: manipulação de eventos.

Source: https://habr.com/ru/post/pt437252/


All Articles