Ciclo de lecciones de SDL 2.0: Lecci贸n 5 - Cortar una hoja de Sprite

imagen

De un traductor:

Esta es una continuaci贸n de una serie de traducciones de tutoriales Twinklebear, disponibles en el original aqu铆 . La traducci贸n es en parte gratuita y puede contener peque帽as modificaciones o adiciones del traductor. Traducci贸n de las dos primeras lecciones - autor铆aPuntero inv谩lidoy el tercero y cuarto para k1-801.


Lista de lecciones:



Rebanadas de hojas de Sprite


A menudo, en juegos 2D, usan una imagen grande para almacenar varias im谩genes m谩s peque帽as, por ejemplo, mosaicos en mosaicos en lugar de muchas im谩genes peque帽as para cada mosaico. Dicha imagen se llama hoja de sprite y es muy conveniente para el trabajo, ya que no necesitamos cambiar la textura que queremos dibujar, solo indicamos qu茅 parte de la textura usar.

En este tutorial, veremos c贸mo seleccionar partes de una textura usando SDL_RenderCopy , as铆 como un poco sobre c贸mo detectar eventos de pulsaci贸n de teclas espec铆ficos que usaremos para seleccionar qu茅 parte de la textura dibujar. Habr谩 cuatro c铆rculos coloridos en la hoja de sprites:

imagen


En este tutorial, una hoja de sprites consta de muchos sprites del mismo tama帽o, en cuyo caso el corte no es dif铆cil. De lo contrario, para sprites de diferentes tama帽os, necesitar铆amos un archivo de metadatos que contenga informaci贸n sobre la ubicaci贸n de las partes. Para este tutorial usaremos 4 sprites de tama帽o 100x100. El c贸digo para esta lecci贸n se basa en la lecci贸n 4, si no tiene un c贸digo para escribir, puede obtenerlo de Github .

Selecci贸n de parte


Con el SDL, es muy f谩cil seleccionar la parte de la textura que desea dibujar. En la lecci贸n 4, los par谩metros restantes de SDL_RenderCopy con un valor NULL indican las coordenadas del rect谩ngulo que determina qu茅 parte de la textura queremos dibujar. Al pasar un valor NULL, indicamos que necesitamos toda la textura, pero podemos agregar f谩cilmente los par谩metros del rect谩ngulo y dibujar solo una parte de la textura. Para hacer esto, realice cambios en la funci贸n renderTexture para que pueda ocupar un 谩rea rectangular, pero a煤n as铆 mantenga una versi贸n corta de la sintaxis de la versi贸n anterior por conveniencia.

Cambiar renderTexture


Para no vincular m谩s y m谩s par谩metros a nuestra funci贸n renderTexture y al mismo tiempo mantener la conveniencia de los valores predeterminados, lo dividiremos en dos funciones. El primero es casi id茅ntico a la llamada SDL_RenderCopy, pero proporciona un par谩metro de regi贸n de recorte con un valor nullptr. Esta versi贸n de renderTexture recibir谩 una ubicaci贸n en forma de 谩rea rectangular, que podemos configurar nosotros mismos o usar una de nuestras otras funciones especializadas de renderTexture. La nueva funci贸n b谩sica de renderizado se est谩 volviendo muy simple.

/**
*  SDL_Texture  SDL_Renderer   .
*     
* @param tex  ,   
* @param ren ,    
* @param dst     
* @param clip     ( )
*                 nullptr   
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, SDL_Rect dst,
        SDL_Rect *clip = nullptr)
{
        SDL_RenderCopy(ren, tex, clip, &dst);
}

Por conveniencia, escribiremos otra funci贸n en la que no necesitemos crear SDL_Rect para la ubicaci贸n, sino que solo proporcione x e y y deje que nuestra funci贸n de visualizaci贸n llene el ancho y la altura de la textura. Crearemos una versi贸n sobrecargada de renderTexture que har谩 esto con algunas configuraciones para manejar el recorte. Agregue un rect谩ngulo de corte como par谩metro con el valor predeterminado nullptr y, en caso de que se apruebe, usaremos el ancho y la altura del corte en lugar del ancho y la altura de la textura. Por lo tanto, no estiraremos el sprite peque帽o al tama帽o de su hoja de sprite potencialmente muy grande cuando se dibuje. Esta funci贸n es una modificaci贸n de la funci贸n renderTexture original y se ve muy similar.

/**
*  SDL_Texture  SDL_Renderer   x, y, 
*          
*    ,       
*          
* @param tex  ,   
* @param ren ,    
* @param x  x,    
* @param y  y,    
* @param clip     ( )
*                 nullptr   
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y,
        SDL_Rect *clip = nullptr)
{
        SDL_Rect dst;
        dst.x = x;
        dst.y = y;
        if (clip != nullptr){
                dst.w = clip->w;
                dst.h = clip->h;
        }
        else {
                SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);
        }
        renderTexture(tex, ren, dst, clip);
}

Definir rect谩ngulos de recorte


En nuestro caso, es muy f谩cil calcular rect谩ngulos de recorte utilizando el m茅todo muy similar al m茅todo de mosaico de la lecci贸n 3 , sin embargo, en lugar de ir l铆nea por l铆nea, iremos columna por columna. Por lo tanto, la primera pieza ser谩 verde, la segunda ser谩 roja, la tercera ser谩 azul y la cuarta ser谩 amarilla. La idea de computaci贸n es la misma que en la lecci贸n 3, pero solo en lugar de filas corremos a trav茅s de las columnas. Por lo tanto, nuestras coordenadas y se calculan obteniendo el resto al dividir el 铆ndice de mosaico por el n煤mero de mosaicos (2), y la coordenada x dividiendo el 铆ndice por el n煤mero de mosaicos. Estas coordenadas x e y son 铆ndices x e y, por lo que las traducimos en coordenadas de p铆xeles reales al multiplicarlas por el ancho y la altura del recorte, que es el mismo para todos los mosaicos (100x100). Finalmente, seleccione la pieza a dibujar, en este caso la primera.

Tambi茅n nos gustar铆a dibujar nuestras piezas en el centro de la pantalla, por lo que calculamos estas coordenadas xey utilizando el ancho y la altura del mosaico en lugar del ancho y la altura de la textura.

//iW  iH    
//   ,     ,     
int iW = 100, iH = 100;
int x = SCREEN_WIDTH / 2 - iW / 2;
int y = SCREEN_HEIGHT / 2 - iH / 2;

//    
SDL_Rect clips[4];
for (int i = 0; i < 4; ++i){
        clips[i].x = i / 2 * iW;
        clips[i].y = i % 2 * iH;
        clips[i].w = iW;
        clips[i].h = iH;
}
//     
int useClip = 0;

Si, en cambio, us谩ramos una hoja de sprites m谩s compleja con sprites rotados de diferentes tama帽os empaquetados, necesitar铆amos almacenar informaci贸n sobre su ubicaci贸n y rotaci贸n en alg煤n archivo de metadatos para que podamos encontrar f谩cilmente las piezas.

Cambiar im谩genes seg煤n la entrada


Para verificar todas las partes de la imagen que creamos, agregamos el procesamiento de entrada del teclado al bucle de procesamiento de eventos y seleccionamos la parte visualizada usando las teclas 1-4. Para determinar si se ha presionado una tecla, puede verificar si el evento es del tipo SDL_KEYDOWN y, de ser as铆, podemos averiguar qu茅 tecla se presion贸 al verificar el c贸digo de tecla dentro del evento usando e.key.keysym.sym. En la wiki hay disponible una lista completa de tipos de eventos , c贸digos clave y otra informaci贸n sobre SDL_Event .

Cuando se presiona la tecla, necesitamos cambiar el valor de useClip al n煤mero de la parte de la imagen que queremos dibujar. Con estos cambios, el bucle de eventos se ve as铆:

while (SDL_PollEvent(&e)){
        if (e.type == SDL_QUIT)
                quit = true;
        //       
        if (e.type == SDL_KEYDOWN){
                switch (e.key.keysym.sym){
                        case SDLK_1:
                                useClip = 0;
                                *break;
                        case SDLK_2:
                                useClip = 1;
                                *break;
                        case SDLK_3:
                                useClip = 2;
                                *break;
                        case SDLK_4:
                                useClip = 3;
                                *break;
                        case SDLK_ESCAPE:
                                quit = true;
                                *break;
                        default:
                                *break;
                }
        }
}

Dibuja una imagen recortada


隆Lo 煤ltimo que debe hacer es obtener la parte correcta de la imagen en la pantalla! Haremos esto llamando a nuestra versi贸n m谩s conveniente de renderTexture para dibujar parte de la imagen sin escalar y transferir la parte que queremos usar (la que se usa en useClip).

SDL_RenderClear(renderer);
renderTexture(image, renderer, x, y, &clips[useClip]);
SDL_RenderPresent(renderer);

Fin de la lecci贸n 5.


Cuando inicie el programa, deber铆a ver la parte 0 (c铆rculo verde) en el centro de la pantalla y poder seleccionar diferentes partes de la imagen con las teclas num茅ricas. Si encuentra alg煤n problema, vuelva a verificar su c贸digo y / o env铆e un correo electr贸nico o un tweet al autor original.

All Articles