Continuando com nossa série de artigos traduzido do site lazyfoo, agora veremos como carregar e renderizar texturas.
Uma importante adição no SDL 2 é a API de renderização de texturas. Isso lhe proporcionará renderização de texturas baseada em hardware de forma rápida e flexível. Nesse artigo, estaremos usando essa nova técnica de renderização.
//Loads individual image as texture SDL_Texture* loadTexture( std::string path ); //The window we'll be rendering to SDL_Window* gWindow = NULL; //The window renderer SDL_Renderer* gRenderer = NULL; //Current displayed texture SDL_Texture* gTexture = NULL;
Texturas em SDL possuem seu próprio tipo de dado que é intuitivamente chamado de SDL_Texture. Quando lidamos com texturas em SDL você precisa de um SDL_Renderer para renderiza-las na tela, por isso declaramos um renderizador chamado “gRenderer”.
Como você também pode ver, temos uma nova rotina de carregamento de imagem com loadTexture e uma textura que declaramos globalmente que iremos ter que carregar.
//Create window gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if( gWindow == NULL ) { printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() ); success = false; } else { //Create renderer for window gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED ); if( gRenderer == NULL ) { printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() ); success = false; } else { //Initialize renderer color SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF ); //Initialize PNG loading int imgFlags = IMG_INIT_PNG; if( !( IMG_Init( imgFlags ) & imgFlags ) ) { printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() ); success = false; } } }
Depois que criamos nossa janela, temos que criar um renderizador para ela de forma que possamos renderizar as texturas nela. Felizmente, isso é feito de forma fácil com uma chamada para SDL_CreateRenderer.
Depois de criar o renderizador, precisamos inicializar a renderização de cores usando SDL_SetRenderDrawColor. Isso irá controlar quais cores são usadas por várias operações de renderização.
SDL_Texture* loadTexture( std::string path ) { //The final texture SDL_Texture* newTexture = NULL; //Load image at specified path SDL_Surface* loadedSurface = IMG_Load( path.c_str() ); if( loadedSurface == NULL ) { printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() ); } else { //Create texture from surface pixels newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface ); if( newTexture == NULL ) { printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() ); } //Get rid of old loaded surface SDL_FreeSurface( loadedSurface ); } return newTexture; }
Nossa função de carregamento de texturas se parece muito com o que tínhamos antes, mas agora ao invés de converter a superfície carregada para o formato de exibição, criamos uma textura a partir da superfície carregada usando SDL_CreateTextureFromSurface. Como antes, essa função cria uma nova textura a partir de uma superfície existente, o que significa que como antes temos que liberar a superfície carregada e então retornar a textura carregada.
bool loadMedia() { //Loading success flag bool success = true; //Load PNG texture gTexture = loadTexture( "07_texture_loading_and_rendering/texture.png" ); if( gTexture == NULL ) { printf( "Failed to load texture image!\n" ); success = false; } return success; } void close() { //Free loaded image SDL_DestroyTexture( gTexture ); gTexture = NULL; //Destroy window SDL_DestroyRenderer( gRenderer ); SDL_DestroyWindow( gWindow ); gWindow = NULL; gRenderer = NULL; //Quit SDL subsystems IMG_Quit(); SDL_Quit(); }
Como o carregamento da textura é abstraída com nossa função de carregamento de imagem, a função loadMedia() funciona praticamente de mesma forma que antes.
Na nossa função de limpeza, temos que lembrar de desalocar nossa texturas usando SDL_DestroyTexture.
//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_RenderClear( gRenderer ); //Render texture to screen SDL_RenderCopy( gRenderer, gTexture, NULL, NULL ); //Update screen SDL_RenderPresent( gRenderer ); }
No loop principal, após o loop de eventos, chamados SDL_RenderClear. Essa função preenche a tela com as cores que foram configuradas com SDL_SetRenderDrawColor.
Com a tela liberada, renderizamos a textura com SDL_RenderCopy. Com atextura renderizada, temos que atualizar a tela, mas como não estamos usando SDL_Surfaces para renderização não podemos usar SDL_UpdateWindowSurface. Ao invés disso, usamos SDL_RenderPresent.