Ciclo de lecciones de SDL 2.0: Lección 3 - Bibliotecas de extensiones de SDL

SDL2

Del traductor:

Continúo la serie abandonada de traducciones de tutoriales de Twinklebear, originalmente disponibles aquí , con el permiso del traductor de las lecciones anteriores de la serie InvalidPointer . Las dos primeras lecciones de una serie de traducciones en la lista son su autoría. La traducción es en parte gratuita y puede contener pequeñas modificaciones o adiciones del traductor.

Lista de lecciones:


Bibliotecas de extensiones SDL


Hasta ese momento, solo usábamos imágenes BMP, ya que este es el único tipo de imagen admitido por la biblioteca principal de SDL 2, y no es muy conveniente. Afortunadamente, hay muchas bibliotecas de extensiones SDL que agregan funciones útiles, por ejemplo, SDL_image le permite cargar muchos tipos de imágenes, SDL_ttf agrega soporte para renderizar texto usando fuentes TTF, SDL_net para soporte de red de bajo nivel y SDL_mixer para salida de audio multicanal.

Instalar extensión


En este tutorial usaremos solo SDL_image, sin embargo, el proceso de instalación para las otras extensiones no es diferente y, en general, casi coincide con el de la instalación de SDL2.

  • Windows (MinGW o Visual Studio): coloque los archivos de extensión descargados de la página del proyecto de extensión en una carpeta con SDL2. Además, deberá copiar SDL2_image, zlib y otros archivos .dll (por ejemplo, libpng) a la carpeta con su archivo ejecutable (o en C: \ Windows \ system32 - aprox. Per. ) Para que se carguen cuando se inicie la aplicación.
  • Linux : instale la extensión utilizando su administrador de paquetes interno, o compile desde la fuente. Si tiene Linux, lo más probable es que ya sepa cómo hacerlo ©.
  • Mac : descargue .dmg del sitio web oficial y siga las instrucciones del archivo Léame.

Además, para usar la extensión, deberá actualizar la lista de archivos de encabezado y bibliotecas de complementos utilizados, tal como se hizo para SDL2.

Antes de comenzar a trabajar con la extensión, debe conectar el archivo <SDL2 / SDL_image.h>, o el archivo correspondiente al nombre de la extensión deseada, después del archivo de encabezado de la SDL a los archivos .c y .cpp que lo utilizan.

Inicializando SDL_image (opcional)


En la primera carga de la imagen de cada tipo, SDL_image inicializa automáticamente el subsistema necesario para este tipo, sin embargo, esto causará un ligero retraso. Para evitar esto, puede preinicializar los subsistemas necesarios utilizando la función IMG_Init. IMG_Init devuelve una máscara de bits con una lista de todos los subsistemas que se han inicializado con éxito en este momento, por lo tanto, para verificar el éxito de la llamada, es necesario verificar que los bits para todos los subsistemas indicados para la inicialización se hayan establecido, por ejemplo, aplicando una máscara al resultado de bitwise I. Para esta lección, solo necesitamos un subsistema PNG. Es importante llevar a cabo esta operación después de SDL_Init.

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


Establecer dimensiones


En esta lección, veremos cómo cargar imágenes usando SDL_image, cómo escalar texturas al renderizar y colocar el fondo con mosaicos de una manera más racional que en la lección anterior: un ciclo basado en el tamaño de las ventanas y los mosaicos.

Pero primero, establezcamos una constante para el tamaño del mosaico, justo debajo de las constantes para el tamaño de la ventana.

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

Carga de imágenes usando SDL_image


SDL_image le permite cargar varios tipos de imágenes, así como convertirlas inmediatamente a SDL_Texture con la función IMG_LoadTexture. Esta función reemplaza casi todo el código de la función loadTexture de la lección anterior, ahora solo llame a IMG_LoadTexture, verifique si hubo algún error durante la carga y salga de la función. Dado que la función IMG_GetError definida en SDL_image no es más que un sinónimo de SDL_GetError, podemos usar cualquiera de ellos para mostrar mensajes de error.

 /** *       * @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 la altura y el ancho para renderizar


Si especifica un tamaño de rectángulo diferente del tamaño de la textura cuando renderiza la textura al renderizador, SDL2 la escalará en consecuencia. Sin embargo, si no se requiere escala, puede ser inconveniente determinar el tamaño inicial de la textura cada vez, por lo que implementaremos dos versiones de la función renderTexture, una de las cuales dibujará la textura con escala y la segunda sin ella.

 /** *  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); } 

Cargando texturas


Dado que el objetivo principal de esta lección es descargar imágenes PNG, utilizaremos un nuevo conjunto de imágenes. Además, demostraremos la preservación de la transparencia PNG al representar una imagen en primer plano (con un fondo transparente) sobre un fondo en mosaico.

Utilizaremos estas imágenes:

Azulejo para llenar el fondo:



Imagen del primer plano (como está escrito en él, con un fondo transparente, así como también con emoticones que violan las reglas de Habr):



Subiendo imágenes:

 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; } 

Fondo de mosaico


Dado que los mosaicos son notablemente más pequeños, necesitaremos colocar más de cuatro piezas para llenar toda la ventana, y será bastante difícil especificar la posición de cada uno manualmente. Afortunadamente, puede hacer que la computadora determine estas posiciones usted mismo.

Podemos averiguar cuántos mosaicos se necesitan en ancho dividiendo el ancho de la ventana por el tamaño del mosaico, y de manera similar para la 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); } 

Dibujo de imagen en primer plano


Como antes, la imagen en primer plano se coloca en el centro de la ventana.

 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); 

Solo queda mostrar el resultado en la ventana y esperar un par de segundos, como en la segunda lección.

 SDL_RenderPresent(renderer); SDL_Delay(2000); 

Limpieza


La liberación de recursos es similar a la de la lección 2 (y ya se ha visto anteriormente al procesar un error al cargar una imagen), a excepción de la llamada adicional IMG_Quit.

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

Después de una compilación e inicio exitosos, si hiciste todo correctamente, la ventana se verá así:



El final de la tercera lección.


Así que la siguiente lección llegó a su fin. Nos vemos en la Lección 4: Manejo de eventos.

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


All Articles