Lições sobre SDL 2: Lição 4 - Alongamento PNG

Olá pessoal! Esta é a quarta lição do SDL 2. Decidi combinar as duas lições em uma, pois no original elas são pequenas. Mas eles podem ser encontrados aqui e aqui . Bem, vamos começar a lição.

Primeiro, decidiremos o que faremos. Hoje, aprenderemos como fazer upload de imagens de outra extensão (não BMP), a saber: PNG. Refaça a imagem em um formato diferente para acelerar o trabalho e redimensionar a imagem. Vamos trabalhar com esta imagem:

imagem

Instalação


Então, primeiro aprendemos a baixar PNG. No conjunto de recursos padrão do SDL 2, não há upload de uma imagem no formato não BMP. Para baixar um formato diferente, você precisa instalar a extensão.

Aqui estão as instruções:

Windows
Você acessa esta página e baixa os arquivos ZIP ou TAR.GZ na seção Bibliotecas de Desenvolvimento . Descompacte e jogue-os na pasta com o compilador.

Linux
Se o seu sistema usa Debian, você precisa inserir estes comandos:

apt-cache search libsdl2-image apt-get install libsdl2-image-dev 

Se o Yellowdog Updater, Modified for usado, você deverá digitar estes comandos:

 yum search SDL2_image-devel yum  SDL2_image-devel 


Mac OS
Faça o download do arquivo DMG e leia o Leia-me.

Escrevendo um código


Depois de definir SDL_image, começamos a escrever o código. Primeiro, como sempre, conectaremos as bibliotecas, definiremos o tamanho das janelas e criaremos 3 variáveis ​​globais.

 #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL; 

Observe que eu conectei o SDL_image.h separadamente, pois é uma biblioteca separada.

Em seguida, escrevemos 3 funções, conhecidas por nós, nas quais vamos adicionar e alterar algo, como de costume.

Init ()
 bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; } 


Aqui nós adicionamos a inicialização do módulo SDL_image. Para inicializá-lo, primeiro crie uma variável int , temos sinalizadores e salve todos os sinalizadores que você deseja usar para a inicialização.

Lista de todos os sinalizadores
SDL_INIT_PNG - inicializa o downloader de imagem PNG;
SDL_INIT_JPG - inicializa o downloader de imagem JPG;
SDL_INIT_TIF - inicializa o downloader de imagem TIF;

Em seguida, escrevemos esta condição:

 if ( !( IMG_Init( flags ) & flags ) ) 

A função IMG_Init () retorna os sinalizadores que pôde inicializar. Se ela devolveu as bandeiras, mas a que queríamos estava faltando, retornamos um erro. Muito simples Além disso, observe que eu uso IMG_GetError em vez de SDL_GetError , pois estamos procurando um erro na função do módulo SDL_image , não no SDL .

Também quero observar que decidi usar o tipo bool para retornar a - esta é uma maneira mais racional.

Vamos continuar escrevendo nosso programa, escrevendo a função Load () , na qual carregamos uma imagem PNG e a convertemos.

Carregar
 bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; } 


Aqui, carregamos a imagem com a nova função IMG_Load . Sua função é a mesma que a de SDL_LoadBMP e o resultado é o mesmo - ele retorna uma instância da classe SDL_Surface . Para encontrar erros durante o carregamento, também usamos IMG_GetError .

É hora de converter. Primeiro, um pouco de teoria. Poucas pessoas sabem, mas ao baixar uma imagem, ela é baixada no formato 24 bits, e a maioria das telas modernas está no formato 32 bits. E toda vez que exibíamos a imagem na tela, ela era refeita pela primeira vez no formato 32 bits. Para programas simples, isso não importa, mas ao criar algum tipo de projeto grande, ele afetará bastante o desempenho; portanto, tomaremos e no estágio de carregamento das imagens as refazeremos no formato de exibição. A função SDL_ConvertSurface ajudará. São necessários três valores: a superfície que queremos formatar, o formato em que queremos formatar e os sinalizadores. queremos formatar a imagem da flor , passe o primeiro parâmetro. O segundo parâmetro é o formato da superfície da janela, não usaremos sinalizadores. Essa função retorna uma cópia da superfície, que atribuímos imediatamente à flor . Para procurar erros, usamos a função SDL_GetError () , porque já estamos trabalhando com superfícies, e elas são do SDL , e não do SDL_image .

Em seguida, escrevemos a função Quit, adicionamos apenas uma função a ela.

Sair
 void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); } 


Adicionamos IMG_Quit para inicializar o módulo SDL_image.

Principal


Agora, a coisa mais simples permanece - a função principal .

 int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; } 

Para começar, inicialize e crie tudo o que você precisa e faça o upload dos arquivos necessários. Nós não vamos parar por aqui.

  SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0; 

Depois disso, crie um objeto da classe SDL_Rect . Vamos precisar para esticar a imagem. Se você notar, a imagem da flor é 4 vezes menor que a janela (2 vezes mais fina e 2 vezes menor), e precisamos esticá-la para a janela. Portanto, na largura do retângulo, bg_flower escreva o valor da largura da janela e em altura - a altura da janela. defina as coordenadas como 0, para que a imagem seja exibida no canto superior esquerdo.

Para exibir imagens redimensionadas, há uma função especial. É assim:

  SDL_BlitScaled(flower, NULL, scr, &bg_flower); 

Leva 4 significados. A primeira é a imagem que queremos exibir, a segunda é o retângulo que queremos cortar desta imagem (se quisermos tirar a imagem inteira, escrevemos NULL), a terceira é a superfície na qual queremos exibir a imagem e a quarta é o mesmo retângulo, dimensões e as coordenadas que usamos para esticar ou comprimir e exibir a imagem.

Em seguida, basta atualizar a superfície da tela, definir o atraso, sair e retornar 0.

  SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; }; 

É aqui que o nosso programa termina. Para compilar esse milagre, você precisa adicionar -lSDL2_image, como outra opção de compilação.

E nisso terminaremos por hoje. Aqui está o código que temos:

 #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL; bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; } bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; } void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); } int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; } SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0; SDL_BlitScaled(flower, NULL, scr, &bg_flower); SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; }; 

Tchau pessoal!

<< Lição anterior || Próxima lição >>

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


All Articles