Ciclo de aula do SDL 2.0: Lição 5 - Cortando uma folha de sprite

imagem

De um tradutor:

Esta é uma continuação de uma série de traduções de tutoriais do Twinklebear, disponíveis no original aqui . A tradução é parcialmente gratuita e pode conter pequenas alterações ou acréscimos do tradutor. Tradução das duas primeiras lições - autoriaInvalidPointere o terceiro e quarto para k1-801.


Lista de lições:



Corte de folhas de Sprite


Geralmente, em jogos 2D, eles usam uma imagem grande para armazenar várias imagens menores, por exemplo, peças em conjuntos de peças em vez de muitas figuras pequenas para cada peça. Essa imagem é chamada de folha de sprite e é muito conveniente para o trabalho, pois não precisamos alterar a textura que queremos desenhar, mas apenas indicar qual parte da textura usar.

Neste tutorial, veremos como selecionar partes de uma textura usando SDL_RenderCopy , bem como um pouco sobre como detectar eventos específicos de pressionamento de tecla que usaremos para selecionar qual parte da textura desenhar. Haverá quatro círculos coloridos na folha de sprite:

imagem


Neste tutorial, uma planilha de sprites consiste em muitos sprites do mesmo tamanho; nesse caso, fatiar não é difícil. Caso contrário, para sprites de tamanhos diferentes, precisaríamos de um arquivo de metadados com informações sobre a localização das peças. Para este tutorial, usaremos 4 sprites de tamanho 100x100. O código desta lição é baseado na lição 4. Se você ainda não tem um código para escrever, pode obtê-lo no Github .

Seleção de peças


Usando o SDL, é muito fácil selecionar a parte da textura que você deseja desenhar. Na lição 4, os parâmetros restantes SDL_RenderCopy com um valor NULL significam as coordenadas do retângulo que determinam qual parte da textura queremos desenhar. Ao passar o valor NULL, indicamos que precisamos de toda a textura, mas podemos adicionar facilmente os parâmetros do retângulo e desenhar apenas parte da textura. Para fazer isso, faça alterações na função renderTexture para que ela ocupe uma área retangular, mas mantenha uma versão curta da sintaxe da versão antiga por conveniência.

Alterar renderTexture


Para não ligar cada vez mais parâmetros à nossa função renderTexture e, ao mesmo tempo, manter a conveniência dos valores padrão, vamos dividi-lo em duas funções. O primeiro é quase idêntico a chamar SDL_RenderCopy, mas fornece um parâmetro de região de recorte com um valor nullptr. Esta versão do renderTexture receberá o local na forma de uma área retangular, que podemos configurar por nós mesmos ou usando uma de nossas outras funções especializadas do renderTexture. A nova função básica de renderização está se tornando muito simples.

/**
*  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 conveniência, escreveremos outra função em que não precisaríamos criar SDL_Rect para o local, mas apenas forneça x e y e deixe nossa função de exibição preencher a largura e a altura da textura. Criaremos uma versão sobrecarregada do renderTexture que fará isso com algumas configurações para lidar com o recorte. Adicione um retângulo de corte como parâmetro com o valor padrão nullptr e, caso o corte tenha sido passado, usaremos a largura e a altura do corte em vez da largura e altura da textura. Portanto, não esticaremos o pequeno sprite até o tamanho de sua folha de sprite potencialmente muito grande quando ele for desenhado. Essa função é uma modificação da função renderTexture original e parece muito semelhante.

/**
*  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 retângulos de recorte


No nosso caso, é muito fácil calcular retângulos de recorte usando o método muito semelhante ao método lado a lado da lição 3 ; no entanto, em vez de ir linha por linha, iremos coluna por coluna. Assim, a primeira peça será verde, a segunda será vermelha, a terceira será azul e a quarta será amarela. A idéia da computação é a mesma da lição 3, mas percorremos as colunas em vez de linhas. Portanto, nossas coordenadas y são calculadas obtendo o restante ao dividir o índice de ladrilhos pelo número de ladrilhos (2) e as coordenadas x dividindo o índice pelo número de ladrilhos. Essas coordenadas x e y são índices x e y; portanto, as traduzimos em coordenadas de pixels reais, multiplicando pela largura e altura do recorte, que é o mesmo para todos os blocos (100x100). Por fim, selecione a peça a desenhar, neste caso a primeira.

Também gostaríamos de desenhar nossas peças no centro da tela, portanto calculamos essas coordenadas x e y usando a largura e a altura do ladrilho em vez da largura e altura da 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;

Se, em vez disso, usarmos uma planilha de sprite mais complexa com sprites girados de tamanhos diferentes reunidos, precisaremos armazenar informações sobre sua localização e rotação em algum arquivo de metadados, para que possamos encontrar peças com facilidade.

Alterar imagens com base na entrada


Para verificar todas as partes da imagem que criamos, adicionamos o processamento de entrada do teclado ao loop de processamento de eventos e selecionamos a parte exibida usando as teclas 1-4. Para determinar se uma tecla foi pressionada, você pode verificar se o evento é do tipo SDL_KEYDOWN e, se houver, podemos descobrir qual tecla foi pressionada verificando o código da tecla dentro do evento usando e.key.keysym.sym. Uma lista completa de tipos de eventos , códigos de chave e outras informações sobre SDL_Event está disponível no wiki.

Quando a tecla é pressionada, precisamos alterar o valor de useClip para o número da parte da imagem que queremos desenhar. Com essas alterações, o loop de eventos fica assim:

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

Desenhar uma imagem cortada


A última coisa a fazer é colocar a parte certa da imagem na tela! Faremos isso chamando nossa versão mais conveniente do renderTexture para desenhar parte da imagem sem redimensionar e transferir a parte que queremos usar (a usada no useClip).

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

Fim da lição 5


Ao iniciar o programa, você verá a parte 0 (círculo verde) no centro da tela e poderá selecionar diferentes partes da imagem usando as teclas numéricas. Se você encontrar algum problema, verifique seu código e / ou envie um e-mail ou tweet ao autor original.

All Articles