Tutorial SDL

Tutorial sobre a biblioteca SDL com exemplos práticos.

[ Hits: 47.822 ]

Por: Samuel Leonardo em 01/11/2013


Aplicação básica



Uma janela

Agora, vamos criar uma aplicação básica em SDL. Ela mostrará uma janela simples e como iniciar/fechar o SDL e, após alguns segundos, fechará.

Arquivo: janela_01.c

#include <SDL/SDL.h> // Inclui a biblioteca SDL

int main()
{
  SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
  SDL_Surface * screen; // A janela principal

  screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela

  SDL_Delay(5000); // Espera 5000 milissegundos OU 5 segundos
  SDL_Quit(); // Fecha o SDL
  return 0;
}

Para compilar:

gcc -o janela_01 janela_01.c -lSDL

Onde:
  • #include <SDL/SDL.h> :: "include a biblioteca SDL. Em SDL.h", estão todos os headers que precisamos.
  • SDL_Init(SDL_INIT_VIDEO); :: inicializa o SDL e o subsistema de vídeo. É possível inicializar mais subsistemas com essa função. Por enquanto, apenas o subsistema de vídeo é o bastante pra esse tutorial.
  • SDL_Surface * screen; :: declara uma SDL_Surface para a janela principal.
  • screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); :: cria uma janela com largura de 640 e altura 480 com 16 bits de profundidade. A flag SDL_SWSURFACE indica que a janela será criada na memória RAM, há outra flag que usa a memória de vídeo (SDL_HWSURFACE) para outras flags digite man SDL_SetVideoMode no terminal. Se ocorrer erro na criação da janela, será retornado NULL, caso contrário, será retornado um ponteiro para uma surface (janela principal).
  • SDL_Delay(5000); :: SDL_Delay faz o programa parar por um tempo determinado. O tempo de espera é um número inteiro e positivo. Geralmente, 10 milissegundos é o bastante para um loop principal.
  • SDL_Quit(); :: essa função deve ser chamada sempre que o programa for terminar. Ela encerra o SDL liberando as SDL_Surfaces alocadas e fechando todos os subsistemas antes inicializados.

Uma janela com imagem

Arquivo: janela_02.c

#include <SDL/SDL.h>
#include <stdio.h>

int main()
{
  SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
  SDL_Surface * screen; // A janela principal
  SDL_Surface * image; // A imagem

  screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
  image = SDL_LoadBMP("ball.bmp"); // Carrega a imagem no formato BMP

  // Verifica se carregou a imagem corretamente

  if (image == NULL)
  {
     printf("Não foi possivel abrir ball.bmp\n");
     return 1;
  }

  SDL_FillRect(screen, NULL, 0x0); // Pinta de preto todo o screen
  SDL_BlitSurface(image, NULL, screen, NULL); // Joga a imagem na tela
  SDL_UpdateRect(screen, 0,0,0,0); // Atualiza o screen com a imagem blitada
  SDL_Delay(5000); // Espera 5000 milissegundos OU 5 segundos
  SDL_Quit(); // Fecha o SDL

  return 0;
}

Para compilar:

gcc -o janela_02 janela_02.c -lSDL

No SDL, as imagens também são SDL_Surface (e ponteiros). Para declarar uma imagem em SDL, basta usar o tipo SDL_Surface:

SDL_Surface * nome_da_variável;

Por padrão, o SDL só carrega imagens no formato BMP, se quiser carregar em PNG, por exemplo, precisará usar outra biblioteca auxiliar (SDL_image). Por enquanto, vou usar apenas o padrão SDL.

De forma geral, para carregar uma imagem, use:

SDL_Surface * nome_da_variável = SDL_LoadBMP("caminho_para_o_arquivo.bmp");

SDL_LoadBMP retorna um ponteiro SDL_Surface, ou NULL, se não conseguir carregar o arquivo. O parâmetro "caminho_para_arquivo.bmp", é o caminho completo para o arquivo de imagem em formato BMP. Toda surface possui largura(w de width) e altura(h de height).

Para acessá-los, use:

nome_da_variável->w para largura e nome_da_variável->h para altura

SDL_FillRect(screen, NULL, 0x0); :: pinta de preto todo o screen.

SDL_BlitSurface(image, NULL, screen, NULL); :: essa função joga uma imagem (ou parte dela) em cima de outra SDL_Surface. O primeiro parâmetro image, é a surface de origem.

O segundo parâmetro NULL é o clip, como ele é nulo, toda a imagem será usada como clip, com ele poderia usar um SDL_Rect para pegar uma parte interna da imagem e jogar no screen.

O terceiro parâmetro screen é a SDL_Surface de destino, é onde será jogada a imagem.

O quarto parâmetro é o destino da imagem dentro da SDL_Surface de destino (o screen). Com esse parâmetro, é possível alterar a posição de image dentro do screen. Como ele, é nulo significa que a image será jogada no destino x = 0 e y = 0. Veremos mais a frente mais informação sobre ele.

SDL_UpdateRect(screen, 0,0,0,0); :: atualiza o screen inteiro. Sempre é preciso atualizar o screen quando se "blita" uma imagem. Mas, não é necessário atualizar todo o screen, poderia atualizar somente uma parte dele, onde se blitou/colocou a imagem. Para mais informações sobre essa função use man SDL_UpdateRect no terminal.

Blitando uma imagem em várias posições

No SDL, os eixo X e Y são orientados da seguinte maneira:
Linux: Tutorial SDL

Sendo o canto superior esquerdo da tela, como o ponto (0, 0). A largura e altura da janela são o máximo de visão que se pode ter. Ou seja, se uma imagem estiver além dos limites da altura e largura da janela, não será vista.

Arquivo: janela_03.c

#include <SDL/SDL.h>

int main()
{
  SDL_Init(SDL_INIT_VIDEO); // Inicializa o SDL e o sistema de vídeo
  SDL_Surface * screen; // A janela principal
  SDL_Surface * image; // A imagem
  SDL_Rect dest; // Destino da imagem

  screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); // Cria a janela
  image = SDL_LoadBMP("ball.bmp"); // Carrega a imagem no formato BMP

  // Verifica se carregou a imagem corretamente

  if (image == NULL)
  {
     printf("Não foi possivel abrir ball.bmp\n");
     return 1;
  }

  // Move a imagem para o ponto X = 0 e Y = 0
  dest.x = 0; // Ponto de destino no eixo X
  dest.y = 0; // Ponto de destino no exito Y
  SDL_FillRect(screen, NULL, 0x0); // Pinta de preto todo o screen
  SDL_BlitSurface(image, NULL, screen, &dest); // Joga a imagem no screen em dest
  SDL_UpdateRect(screen, 0,0,0,0); // Atualiza o screen com a imagem blitada
  SDL_Delay(5000); // Espera 5000 milissegundos OU 5 segundos

  // Move a imagem para o ponto X = 10 e Y = 15

  dest.x = 10; // Ponto de destino no eixo X
  dest.y = 15; // Ponto de destino no exito Y
  SDL_FillRect(screen, NULL, 0x0); // Pinta de preto todo o screen
  SDL_BlitSurface(image, NULL, screen, &dest); // Joga a imagem no screen em dest
  SDL_UpdateRect(screen, 0,0,0,0); // Atualiza o screen com a imagem blitada
  SDL_Delay(5000); // Espera 5000 milissegundos OU 5 segundos

  // Move a imagem para o ponto X = 40 e Y = 25

  dest.x = 40; // Ponto de destino no eixo X
  dest.y = 25; // Ponto de destino no exito Y
  SDL_FillRect(screen, NULL, 0x0); // Pinta de preto todo o screen
  SDL_BlitSurface(image, NULL, screen, &dest); // Joga a imagem no screen em dest
  SDL_UpdateRect(screen, 0,0,0,0); // Atualiza o screen com a imagem blitada
  SDL_Delay(5000); // Espera 5000 milissegundos OU 5 segundos

  SDL_Quit(); // Fecha o SDL

  return 0;
}

Para compilar:

gcc -o janela_03 janela_03.c -lSDL

Observe que, antes da chamada de SDL_BlitSurface, chamei SDL_FillRect para pintar todo o screen de preto. O segundo parâmetro NULL indica que vamos pintar todo o screen com uma cor.

A cor usada no screen é 0x0 em hexadecimal, mas se quiser outra cor, é só usar no lugar de 0x0 SDL_MapRGB(screen->format, "VERMELHO", "VERDE", "AZUL") "VERMELHO", "VERDE" e "AZUL" são números inteiros.

SDL_MapRGB criará uma cor com o valor de "VERMELHO", "VERDE" e "AZUL". Cada cor primária é um número inteiro de 0 até 255, indicando a quantidade de cada cor primária para criar uma cor combinada.

Por exemplo, para pintar todo o screen de amarelo, use (antes de SDL_BlitSurface): SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 0).

SDL_Rect dest; :: essa variável será usada para colocar a image em várias posições diferentes dentro do screen.

Todo SDL_Rect tem 4 membros: x, y, w e h. Os membros x e y são as coordenadas da tela, e o w e h são largura (w de width) e altura (h de height).

Toda vez que mudar a posição da imagem através de dest, será preciso reblitar a imagem no screen.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Aplicação básica
   3. Dando vida ao programa: o loop principal
   4. Eventos no SDL
   5. Controlando uma imagem com o teclado
Outros artigos deste autor

Programação de Jogos com SDL

Desenhando fácil um pinguim no Inkscape

Algoritmo Antissocial - Recuperando o Controle da sua Mente

Criatividade para TI parte 1

Dicas para aprender programação

Leitura recomendada

Dicas para aprender programação

Linguagem C - Árvores Binárias

Análise dos Métodos de Ordenação usados em Algoritmos Computacionais

Linguagem C - Listas Duplamente Encadeadas

Algoritmo... como fazer?

  
Comentários
[1] Comentário enviado por nelson777 em 01/11/2013 - 15:40h

Finalmente um artigo de C que não é só mais um algoritmo básico de criança e sim algo útil. Parabéns.

[2] Comentário enviado por tsuriu em 03/11/2013 - 20:49h

Parabéns cara... Muito bom o artigo.

[3] Comentário enviado por danilo3610 em 04/11/2013 - 08:53h

Muito bom tutorial Samuel, segui passo a passo este tutorial no meu ubuntu 13.10 64bits,
instalei o SDL_DEV e usei o seu primeiro exemplo porem ao compilar (incluindo -ISDL)
apresentava erros com SDL_Init - "Undefined reference to SDL_Init...". Procurei na net
mas ninguem teve este mesmo problema, já aconteceu com alguem? Se alguem tiver alguma
solução agradeço. Lembrando instalei o SDL_DEV como mostra o tutorial.

att.

[4] Comentário enviado por SamL em 04/11/2013 - 11:32h

Esse problema geralmente acontece quando NÃO se usa -lSDL no final do comando. Veja se você compilou assim: gcc -o janela_01 janela_01.c -lSDL
com o link -lSDL no final.
Se não resolver talvez você tenha instalado a SDL 2.0, veja na pasta /usr/include/ se tem a pasta SDL2.
Se também não resolver, não sei mais o que fazer rsrsrs

[5] Comentário enviado por danilo3610 em 04/11/2013 - 14:00h

Talvez tenha confundido mas só uma duvida, a primeira letra é um l ou i maiúsculo? Desconfio que seja um L minúsculo e
tenha colocado um i maiúsculo no lugar. Quando chegar em casa irei testar.

[6] Comentário enviado por SamL em 04/11/2013 - 14:03h

É um L minúsculo. Avisa se funcionar quando testar.

[7] Comentário enviado por danilo3610 em 04/11/2013 - 19:24h

Era isso mesmo, troquei o I pelo l e funcionou, obrigado.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts