Uma rápida olhada no SDL

Share

O SDL – Simple DirectMedia Layer – é um conjunto de bibliotecas desenvolvido para construir aplicações multimídia com imagens, áudio, vídeo e um bom desempenho. Estas aplicações são portáveis entre diversos sistemas operacionais e há implementações em diversas linguagens de programação. Neste post vamos lidar com o mínimo necessário para se criar uma aplicação em C que faz uma animação com imagens.

O malvadão!

Configurando o ambiente: Windows

Dev-C++

Para quem utiliza o Dev-C++, é necessário instalar o devpak do SDL disponível em http://devpaks.org/details.php?devpak=12. Após baixar o arquivo, é só adicioná-lo no Dev-C++ no menu Ferramentas>Package Manager>Install. Após a instalação do devpak, é possível criar um Novo Projeto>Multimedia>SDL.

Linux

Ubuntu

No Ubuntu basta ter acesso ao suders para dar um:

sudo apt-get install libsdl1.2-dev  libsdl-image1.2-dev

Para compilar os exemplos utilize o seguinte comando

gcc -lSDL -lSDL_image arquivo.c -o executavel

Primeiro vamos criar uma aplicação mínima que inicia o SDL para checar se sua instalação está correta. Crie a seguinte estrutura:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main( int argc, char* argv[])
{
   SDL_Init(SDL_INIT_EVERYTHING);
   SDL_Quit();
}

Se compilou sem erros, sua instalação está ok. Agora vamos adicionar uma tela aonde vamos fazer tudo acontecer:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main( int argc, char* argv[])
{
   SDL_Surface *screen;
   SDL_Init(SDL_INIT_EVERYTHING);
   screen = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
   SDL_Quit();
}

Neste ponto vemos que a screen, ou nossa “tela” aparece, mas logo em seguida é finalizada pelo SDL_Quit().

Vamos inserir um laço infinito que vai ficar rodando sem parar, escutando por eventos do teclado. Por enquanto a unica coisa que ele vai responder é ao apertar da tecla ESC, quando irá encerrar o programa:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main( int argc, char* argv[])
{
   SDL_Surface *screen;
   SDL_Event event;
   SDL_Init(SDL_INIT_EVERYTHING);
   screen = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
 
   while(1){
      if( SDL_PollEvent( &event ) ){
         switch(event.type){
         case SDL_KEYDOWN:
	         switch(event.key.keysym.sym) {
            case SDLK_ESCAPE:
               SDL_Quit();
               exit(0);                  
               break;
            default:
               break;
            }
            break;
         default:
            break;
         }
      }
   }
   SDL_Quit();
}

Vamos agora carregar uma imagem do disco em uma variável:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main( int argc, char* argv[])
{
   SDL_Surface *screen;
   SDL_Event event;
   SDL_Init(SDL_INIT_EVERYTHING);
   screen = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
 
   SDL_Surface *alienImage = IMG_Load("space_invader.bmp");
   SDL_SetColorKey(alienImage, (SDL_SRCCOLORKEY|SDL_RLEACCEL),
         SDL_MapRGB(alienImage->format, 255, 255, 255));
 
   SDL_Rect alienPos;
   alienPos.x = 0;
   alienPos.y = 10;
   alienPos.h = alienImage->h;
   alienPos.w = alienImage->w;
 
   while(1){
      SDL_BlitSurface(alienImage,NULL,screen,&alienPos);
      SDL_Flip(screen);
 
      if( SDL_PollEvent( &event ) ){
         switch(event.type){
         case SDL_KEYDOWN:
	         switch(event.key.keysym.sym) {
            case SDLK_ESCAPE:
               SDL_Quit();
               exit(0);                  
               break;
            default:
               break;
            }
            break;
         default:
            break;
         }
      }
 }
   SDL_FreeSurface(alienImage);
   SDL_Quit();
}

O comando SDL_BlitSurface() desenha a imagem no buffer (invisível, somente na memória) de nossa tela (visível) e o comando SDL_Flip() troca o buffer com a imagem visível. Isso é feito porque desenhar na memória é muito mais rápido que desenhar na tela diretamente.

Com isso, nossa imagem terá a cor branca como transparente na hora de pintar e apenas parada na tela.

Vamos adicionar um pouco de movimento fazendo a imagem ir de um lado a outro da tela:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main( int argc, char* argv[])
{
   SDL_Surface *screen;
   SDL_Event event;
   SDL_Init(SDL_INIT_EVERYTHING);
   screen = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
 
   SDL_Surface *alienImage = IMG_Load("space_invader.bmp");
   SDL_SetColorKey(alienImage, (SDL_SRCCOLORKEY|SDL_RLEACCEL),
         SDL_MapRGB(alienImage->format, 255, 255, 255));
 
   SDL_Rect alienPos;
   alienPos.x = 0;
   alienPos.y = 10;
   alienPos.h = alienImage->h;
   alienPos.w = alienImage->w;
 
   while(1){
      SDL_BlitSurface(alienImage,NULL,screen,&alienPos);
      SDL_Flip(screen);
 
      if(alienPos.x>640){
         alienPos.x = 0;
      }else{
         alienPos.x = alienPos.x + 5;
      }
 
      if( SDL_PollEvent( &event ) ){
         switch(event.type){
         case SDL_KEYDOWN:
	         switch(event.key.keysym.sym) {
            case SDLK_ESCAPE:
               SDL_Quit();
               exit(0);                  
               break;
            default:
               break;
            }
            break;
         default:
            break;
         }
      }
   }
   SDL_FreeSurface(alienImage);
   SDL_Quit();
}

As coisas se mexeram, porém, a imagem “borrou” a tela toda. Vamos então, antes de mover o alien, desenhar um retângulo preto cobrindo toda a tela. Por último inserimos uma espera para o movimento ficar mais suave:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main( int argc, char* argv[])
{
   SDL_Surface *screen;
   SDL_Event event;
   SDL_Init(SDL_INIT_EVERYTHING);
   screen = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
 
   SDL_Surface *alienImage = IMG_Load("space_invader.bmp");
   SDL_SetColorKey(alienImage, (SDL_SRCCOLORKEY|SDL_RLEACCEL),
         SDL_MapRGB(alienImage->format, 255, 255, 255));
 
   SDL_Rect alienPos;
   alienPos.x = 0;
   alienPos.y = 10;
   alienPos.h = alienImage->h;
   alienPos.w = alienImage->w;
 
   while(1){
		SDL_FillRect(screen, NULL, 0);
 
      SDL_BlitSurface(alienImage,NULL,screen,&alienPos);
      SDL_Flip(screen);
 
      if(alienPos.x>640){
         alienPos.x = -(alienImage->w);
      }else{
         alienPos.x = alienPos.x + 5;
      }
 
      if( SDL_PollEvent( &event ) ){
         switch(event.type){
         case SDL_KEYDOWN:
	         switch(event.key.keysym.sym) {
            case SDLK_ESCAPE:
               SDL_Quit();
               exit(0);                  
               break;
            default:
               break;
            }
            break;
         default:
            break;
         }
      }
      SDL_Delay(50);
   }
   SDL_FreeSurface(alienImage);
   SDL_Quit();
}

Podemos usar algumas funções matemáticas para construir as trajetórias que nosso personagem vai seguir:

#include "SDL/SDL.h"
#include "math.h"
#include "SDL/SDL_image.h"
int main( int argc, char* argv[])
{
   SDL_Surface *screen;
   SDL_Event event;
   SDL_Init(SDL_INIT_EVERYTHING);
   screen = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
 
   SDL_Surface *alienImage = IMG_Load("space_invader.bmp");
   SDL_SetColorKey(alienImage, (SDL_SRCCOLORKEY|SDL_RLEACCEL),
         SDL_MapRGB(alienImage->format, 255, 255, 255));
 
   SDL_Rect alienPos;
   alienPos.x = 0;
   alienPos.y = 10;
   alienPos.h = alienImage->h;
   alienPos.w = alienImage->w;
 
	float c = 0.0;
 
   while(1){
		SDL_FillRect(screen, NULL, 0);
 
      SDL_BlitSurface(alienImage,NULL,screen,&alienPos);
      SDL_Flip(screen);
 
      if(c>2*M_PI){
         c = 0.0;
      }else{
         c = c + 0.05;
         alienPos.x = (600/2)*(1+cos(c));
      }
      if(alienPos.y>480){
         alienPos.y = -(alienImage->h);
      }else{
         alienPos.y = alienPos.y + 10;
      }
 
      if( SDL_PollEvent( &event ) ){
         switch(event.type){
         case SDL_KEYDOWN:
	         switch(event.key.keysym.sym) {
            case SDLK_ESCAPE:
               SDL_Quit();
               exit(0);                  
               break;
            default:
               break;
            }
            break;
         default:
            break;
         }
      }
      SDL_Delay(50);
   }
   SDL_FreeSurface(alienImage);
   SDL_Quit();
}

Com isto é possível criar algumas animações bem básicas e ter uma idéia do funcionamento do SDL. Entretanto, existem muito mais recursos e técnicas disponíveis para aumentar o desempenho (e segurança) da aplicação e só um estudo mais aprofundado do SDL pode mostrar tais.

Veja também: http://igorknop.com.br/wp/hobby/sdl-intro-2.

Share
Sobre

Um geek ermitão

Publicado em Hobby Marcado com: ,

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

*