Tutorial de SDL – Parte 15 – Rotação e lançamento

Continuando nossa série de artigos traduzido do site lazyfoo, dessa vez aproveitaremos o recurso de renderização de texturas acelerada por hardware do SDL para rotação e lançamento de imagens. Nesse artigo, usaremos esse recursos para fazer com que a textura de uma seta seja girada e lancada.

//Texture wrapper class
class LTexture
{
 public:
 //Initializes variables
 LTexture();
 //Deallocates memory
 ~LTexture();
 //Loads image at specified path
 bool loadFromFile( std::string path );
 //Deallocates texture
 void free();
 //Set color modulation
 void setColor( Uint8 red, Uint8 green, Uint8 blue );
 //Set blending
 void setBlendMode( SDL_BlendMode blending );
 //Set alpha modulation
 void setAlpha( Uint8 alpha );
 //Renders texture at given point
 void render( int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );
 //Gets image dimensions
 int getWidth();
 int getHeight();
 private:
 //The actual hardware texture
 SDL_Texture* mTexture;
 //Image dimensions
 int mWidth;
 int mHeight;
};

Aqui adicionamos mais funcionalidades à classe de textura. A função de renderização agora recebe um angulo de rotacão, um ponto para rotacionar a textura, e uma enumeração de lançamento do SDL.
Como no caso do recorte de retângulos, fornecemos valores padrão aos argumentos no caso de você querer renderizar a textura sem rotaciona-la ou lança-la.

void LTexture::render( int x, int y, SDL_Rect* clip, double angle, SDL_Point* center, SDL_RendererFlip flip )
{
 //Set rendering space and render to screen
 SDL_Rect renderQuad = { x, y, mWidth, mHeight };
 //Set clip rendering dimensions
 if( clip != NULL )
 {
 renderQuad.w = clip->w;
 renderQuad.h = clip->h;
 }
 //Render to screen
 SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );
}

Como você pode ver, tudo que temos que fazer é passar nossos argumentos para nossa funcão SDL_RenderCopyEx. Esse função funciona de forma similar à função SDL_RenderCopy, mas com argumentos adicionais para rotação e lançamento.

 //Main loop flag
 bool quit = false;
 //Event handler
 SDL_Event e;
 //Angle of rotation
 double degrees = 0;
 //Flip type
 SDL_RendererFlip flipType = SDL_FLIP_NONE;

Antes de entramos no loop principal, declaramos variáveis para manter registro do ângulo de rotação de tipo de lançamento.

 //Handle events on queue
 while( SDL_PollEvent( &e ) != 0 )
 {
 //User requests quit
 if( e.type == SDL_QUIT )
 {
 quit = true;
 }
 else if( e.type == SDL_KEYDOWN )
 {
 switch( e.key.keysym.sym )
 {
 case SDLK_a:
 degrees -= 60;
 break;
 case SDLK_d:
 degrees += 60;
 break;
 case SDLK_q:
 flipType = SDL_FLIP_HORIZONTAL;
 break;
 case SDLK_w:
 flipType = SDL_FLIP_NONE;
 break;
 case SDLK_e:
 flipType = SDL_FLIP_VERTICAL;
 break;
 }
 }
 }

No loop de eventos, queremos aumentar ou diminuir a rotação com as teclas ad e alterar o tipo de lançamento com as teclas qwe.

 //Clear screen
 SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
 SDL_RenderClear( gRenderer );
 //Render arrow
 gArrowTexture.render( ( SCREEN_WIDTH - gArrowTexture.getWidth() ) / 2, ( SCREEN_HEIGHT - gArrowTexture.getHeight() ) / 2, NULL, degrees, NULL, flipType );
 //Update screen
 SDL_RenderPresent( gRenderer );

Agora fazemos a renderização de fato. Primeiro informamos as coordenadas xy. Essa pode parecer uma equação complicada, mas tudo o que é feito é achar o centro da imagem. Se a imagem tiver 440 pixels de largura em uma tela de 640 pixels de largura, queremos que a imagem seja fique com 100 pixels de cada lado. Em outras palavras, a coordenada x será a largura da tela (640) menos a largura da imagem (440) tudo dividido por 2 ( (640 – 440) / 2 = 100 ).
O argumento seguinte é o retângulo a ser recortado, e como estamos renderizando toda a textura seu valor será null. O argumento seguinte é o ângulo de rotação em graus. O argumento seguinte é ponto onde iremos rotacionar a imagem. Quando esse valor é null, iremos rotacionar a imagem em torno de seu centro. O último argumento é como a imagem será lancada.
A melhor maneira de entender como usar rotação é testa-la. Experimento para ver os tipos de efeito que você consegue combinando diferentes rotações e lançamentos.
Baixe os arquivo de mídia e código fonte desse artigo aqui.