Depois de configurarmos a SDL, está na hora de começar a parte divertida: usá-la!
Para isto, vamos começar com o clássico Hello World!. Ao final do tutorial teremos algo parecido com isto:

Este código foi feito pelo Lazy Foo. Modificado e traduzido por mim.
Então, vamos começar. Abra seu editor preferido.
1 2 3 | #include "SDL/SDL.h" #include <string> using std::string; |
Aqui só incluímos os headers que iremos utilizar. No caso, SDL e String.
4 5 6 7 | //Constantes const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; const int SCREEN_BPP = 32; |
Nesta parte setamos as contantes de, respectivamente, o comprimento, altura, e bpp(bytes per pixel) da tela. Usarmos um BPP com 32 significa que além dos valores de vermelho, verde e azul(RGB), também temos o valor da claridade(alpha) de cada pixel.
8 9 10 | //Superficies utilizadas SDL_Surface *tux = NULL; SDL_Surface *tela = NULL; |
Aqui setamos dois ponteiros para os SDL_Surface que iremos utilizar. SDL_Surface é uma estrutura que representa uma área onde nós poderemos desenhar. Imagine-a como um pedaço de papel em branco, até agora.
12 13 14 15 16 17 18 19 | //Feito por Lazy Foo SDL_Surface *load_image( string filename ) { //Variável temporária para a imagem que será carregada SDL_Surface* loadedImage = NULL; //Imagem otimizada para o BPP da tela SDL_Surface* optimizedImage = NULL; |
Esta é a nossa função para carregar uma imagem.
Ela recebe o caminho para a imagem e retorna um ponteiro para um SDL_Surface contendo uma versão otimizada da imagem.
A variável loadedImage é aonde nós iremos carregar temporariamente a imagem que está em filename. optimizedImage é a versão otimizada da imagem.
20 21 | //Carrega a imagem loadedImage = SDL_LoadBMP( filename.c_str() ); |
Aqui nós carregamos a imagem para loadedImage.
Nós não devemos utilizá-la agora pois ela tem 24 bits, e nossa tela tem 32 bits. Devemos evitar blitar(é como “colar” uma superfície em cima da outra) uma superfície em outra que tenha um BPP diferente, pois a SDL terá que convertê-la antes disso, o que irá tornar o jogo mais lento.
22 23 24 25 26 27 28 29 30 | //Se não houveram problemas carregando a imagem if( loadedImage != NULL ) { //Cria uma imagem otimizada optimizedImage = SDL_DisplayFormat( loadedImage ); //Libera a imagem antiga SDL_FreeSurface( loadedImage ); } |
Primeiro checamos se ele carregou sem erros a imagem. Se sim, criamos uma versão otimizada da mesma. A função SDL_DisplayFormat() recebe como parâmetro um SDL_Surface* e retorna outro SDL_Surface* com o mesmo BPP da tela.
Depois de termos a imagem otimizada, não precisamos mais da loadedImage, então a liberamos através da SDL_FreeSurface().
31 32 33 | //Retorna a imagem otimizada return optimizedImage; } |
Retornamos a versão otimizada da imagem.
34 35 36 37 38 39 40 41 | //Feito por Lazy Foo void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination ) { //Cria um SDL_Rect temporário para guardar as coordenadas para onde blitar a imagem SDL_Rect offset; //Salva as coordenadas no SDL_Rect offset.x = x; offset.y = y; |
Esta é nossa função para blitar superfícies.
Ela recebe as coordenadas da onde você quer blitar a superfície, qual a superfície que você quer blitar, e em qual superfície você quer blitá-la.
Para isso, primeiro nós colocamos as coordenadas em um SDL_Rect, que é uma estrutura bem simples, com somente quatro elementos: as coordenadas x e y, o comprimento(w) e a altura(h). Fazemos isso pois o método que iremos utilizar, SDL_BlitSurface() só aceita as coordenadas dentro de um SDL_Rect.
42 43 44 | //Blita a superfície SDL_BlitSurface( source, NULL, destination, &offset ); } |
Aqui nos blitamos a superfície com a função SDL_BlitSurface().
Ela recebe quatro parâmetros: a superfície que você quer blitar; a parte da superfície que você quer blitar(bom para sprites, mas, como queremos que ele envie a imagem inteira, usamos NULL); a superfície onde você quer blitar; o endereço do SDL_Rect com as coordenadas da onde blitar.
45 46 47 | //Início do main int main (int argc, char* args[]) { |
Finalmente iniciamos a main. Quando usar a SDL você tem que ter cuidado para só usar a main assim como usamos ou
int main (int argc, char** args)
Qualquer outro jeito não irá funcionar.
48 49 50 51 52 | // Inicializamos a SDL e todos seus subsistemas if (SDL_Init(SDL_INIT_EVERYTHING) == -1) { return 1; } |
Aqui inicializamos a SDL pela função SDL_Init(). Passamos SDL_INIT_EVERYTHING para ele iniciar todos os subsistemas, como audio, vídeo, timers, etc..
Caso ela não consiga inicializar, a função irá retornar -1, e nós sairemos do programa com o código de erro 1.
53 54 | //Inicializa a tela tela = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE ); |
A função SDL_SetVideoMode() cria nossa tela com o tamanho, altura, bpp especificados. O último parâmetro são as flags da tela. Como, por exemplo, se usaremos OpenGL, a memória da placa-de-vídeo, etc. Aqui nós criamos a tela na memória do sistema.
55 56 57 58 59 | //Se houve algum erro na inicialização da tela if (tela == NULL) { return 1; } |
Caso a SDL não tenha conseguido inicializar a tela, paramos a execução com o código de erro 1.
60 61 | //Muda o nome da janela SDL_WM_SetCaption( "Hello World", NULL ); |
Mudamos o nome da janela para Hello World. O segundo parâmetro da função é para o nome do ícone, que não usaremos.
62 63 | //Pinta a tela de branco SDL_FillRect(tela, NULL, 0xFFFFFFFF); |
Usamos a função SDL_FillRect() para pintar a tela de branco. Esta função recebe como parâmetros a superfície que você quer pintar, um SDL_Rect*, caso você queira pintar só uma parte da superfície, e a cor, em RGBA, para pintar.
64 65 | //Carrega a imagem tux = load_image("tux.bmp"); |
Carregamos a imagem do tux usando a função load_image() do Lazy Foo.
66 67 | //Aplicamos o Tux à tela apply_surface( 180, 140, tux, tela ); |
Aplicamos, ou blitamos, o tux a tela usando a função apply_surface() do Lazy Foo.
Lembre-se que na SDL, como na maioria dos lugares em computação, a coordenada y é diferente da matemática. Ela cresce de cima para baixo, ao invés de ser de baixo pra cima.
68 69 70 71 72 | //Atualiza a tela if (SDL_Flip(tela) == -1) { return 1; } |
Até agora nós só estavamos escrevendo no buffer. As imagens só são mostradas quando chamamos o método SDL_Flip() com a superfície que queremos atualizar. Esta função retorna -1 em caso de erro. Nós testamos isso e, caso positivo, paramos a execução do programa com o código de erro 1.
73 74 | //Para a execução por 5 segundos SDL_Delay(5000); |
Nós chamamos a função SDL_Delay() para que consigamos ver alguma coisa, caso contrário o programa iria abrir e fechar tão rápido que não veríamos nada. Ele recebe como parâmetro o tempo em milissegundos(um segundo tem 1000 milissegundos) que queremos pausar a execução.
75 76 77 78 79 80 81 82 83 | //Libera a superfície SDL_FreeSurface(tux); //Destrói a SDL SDL_Quit(); //Termina a execução return 0; } |
Aqui nós limpamos o que usamos durante a execução do programa. Com a função SDL_FreeSurface() nós liberamos a memória das superfícies que usamos. Não precisamos liberar a tela, pois o SDL_Quit() cuida disso.
Baixe os fontes e a imagem deste tutorial aqui.
Posts relacionados:

0 comentários