Tutorial de SDL – Parte 8 – Renderizando imagens geométricas

Continuando com nossa série de artigos traduzidos do site lazyfoo, agora vamos ver como renderizar imagens com base em figuras geométricas.

Além da nova API para renderização de texturas, o SDL possui novas chamadas de renderização de primitivas como parte da sua API de renderização. Assim, se você precisar renderizar formas básicas e  não quiser criar gráficos adicionais para elas, o SDL pode lhe poupar algum trabalho.

bool loadMedia()
{
    //Loading success flag
    bool success = true;

    //Nothing to load
    return success;
}

Como você pode ver na nossa função de carregamento de arquivo de mídia, não carregamos nenhum arquivo de mídia. As primitivas de renderização do SDL permitem que você renderize formas sem carregar gráficos.

            //While application is running
            while( !quit )
            {
                //Handle events on queue
                while( SDL_PollEvent( &e ) != 0 )
                {
                    //User requests quit
                    if( e.type == SDL_QUIT )
                    {
                        quit = true;
                    }
                }

                //Clear screen
                SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
                SDL_RenderClear( gRenderer );

Na parte superior do loop principal lidamos com o evento de saída como antes e limpamos a tela. Observe também que ajustamos a cor para branco com SDL_SetRenderDrawColor para cada frame ao contrário de ajustar uma única vez na função de inicialização. Nós veremos o porquê disso quando chegarmos no final do loop principal.

                //Render red filled quad
                SDL_Rect fillRect = { SCREEN_WIDTH / 4, SCREEN_HEIGHT / 4, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 };
                SDL_SetRenderDrawColor( gRenderer, 0xFF, 0x00, 0x00, 0xFF );
                SDL_RenderFillRect( gRenderer, &fillRect );

A primeira primitiva que iremos desenhar é um retângulo preenchido, que é um retângulo sólido.

Em primeiro lugar definimos um retângulo para definir a área que queremos preencher com uma cor. Se você nunca viu uma estrutura sendo inicializada dessa forma, saiba que as variáveis membro que formam um  retângulo no SDL são xywh para as posições xy, largura e altura, respectivamente. Você pode inicializar uma estrutura fornecendo um array de variáveis na ordem que estas variáveis são declaradas na estrutura.  Aqui estamos criando um retângulo que ocupa um quarto da largura da tela na direção x, um quarto da altura da tela na direção y, e com metade da altura/largura da tela.

Depois de definir a área retângular, ajustamos a cor de renderização com SDL_SetRenderDrawColor. Essa função recebe o renderizador da janela que estamos usando e os valores RGBA das cores que queremos renderizar. R é o componente vermelho, G é o verde, B é o azul e A o componente alpha. O componente alpha controla quão opaco algo será e será coberto no artigo sobre transparência. Esses valores vão de 0 a 255 (ou hexadecimal FF como visto acima) e são misturados para criar todas as cores vistas na tela. Essa chamada para SDL_SetRenderDrawColor ajusta a cor para vermelho opaco.

Depois que o retângulo e as cores tiverem sido ajustadas, SDL_RenderFillRect é chamada para desenhar o retângulo.

                //Render green outlined quad
                SDL_Rect outlineRect = { SCREEN_WIDTH / 6, SCREEN_HEIGHT / 6, SCREEN_WIDTH * 2 / 3, SCREEN_HEIGHT * 2 / 3 };
                SDL_SetRenderDrawColor( gRenderer, 0x00, 0xFF, 0x00, 0xFF );
                SDL_RenderDrawRect( gRenderer, &outlineRect );

Você pode também desenhar o contorno de um retângulo como um centro vazio usando SDL_RenderDrawRect. Como você pode ver, funciona praticamente da mesma forma que o desenho de um retângulo preenchido, pois esse pedaço do código é quase o mesmo do código acima. A principal diferença é que esse retângulo ocupa2 terços da tela e a cor usada aqui é verde.

Além disso, se você mexer com a posição do retângulo, irá notar algo estranho como a coordenada y. Aumentar a coordenada y faz com que o retângulo desça na tela e diminuir esta coordenada faz com que ele suba na tela. Isso se deve porque o SDL e muitas API de renderização 2D usam um sistema de coordenadas diferente.

Na aula de álgebra, você provavelmente aprendeu o sistema de coordenadas cartesiano:

cart_coords

Onde o eixo x aponta para a direita, o eixo y aponta para cima, e a origem fica no canto inferior esquerdo.

O SDL usa um sistema de coordenadas diferente:

sdl_coords

O eixo x aponta para a direita, mas o eixo y aponta para baixo e a origem fica no canto superior esquerdo.

Assim, quando renderizamos um retângulo sólido, o sistema de coordenadas funciona dessa forma:

rect_coords

Uma coisa que você precisa sabe é que o SDL renderiza retângulos, superfícies e texturas da parte superior para a inferior.

                //Draw blue horizontal line
                SDL_SetRenderDrawColor( gRenderer, 0x00, 0x00, 0xFF, 0xFF );
                SDL_RenderDrawLine( gRenderer, 0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT / 2 );

Aqui temos o código para desenhar uma linha com um pixel de altura usando SDL_RenderDrawLine. Primeiro ajustamos a cor para azul, e em seguida fornecemos à chamada de renderização a posição x/y inicial e final da linha. Essas posições farão com que pixels sejam desenhados horizontalmente na tela.

                //Draw vertical line of yellow dots
                SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0x00, 0xFF );
                for( int i = 0; i < SCREEN_HEIGHT; i += 4 )
                {
                    SDL_RenderDrawPoint( gRenderer, SCREEN_WIDTH / 2, i );
                }

                //Update screen
                SDL_RenderPresent( gRenderer );
            }

A última parte de geometria que renderizamos é uma sequência de pontos usando SDL_RenderDrawPoint. Aqui apenas pegamos um conjunto de pontos e desenhamos eles de cima a baixo. Novamente, observe que a coordenada y e o eixo invertido y. Depois que terminamos de desenhar toda as formas geométricas, atualizamos a tela.

Observe a chamada para SDL_SetRenderDrawColor. Estamos usando 255 para o componente vermelho e 255 para o verde, que combinados formam a cor amarela. Lembra da chamada para SDL_SetRenderDrawColor na parte superior do loop? Se ela não estivesse lá, a tela seria exibida com quaisquer que fosse a cor que fosse ajustada por último com SDL_SetRenderDrawColor, o que resultaria em um fundo amarelo nesse caso.

Baixe o código fonte e os arquivos de mídia dessa artigo aqui.