Introdução a SDL Video
Vídeo é provavelmente a coisa mais comum para qual SDL é usado, e, este é o seu subsistema mais completo. Aqui vão alguns exemplos para demonstrar os seus fundamentos.
Iniciando o Display de Vídeo
Isto é o que quase todos os programas SDL tem que fazer, de uma maneira ou de outra.
Exemplo 2-1. Iniciando o Display de Vídeo
SDL_Surface *screen;
/* Inicia a biblioteca SDL */
if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr,"Não foi possível iniciar SDL: %s\n", SDL_GetError());
exit(1);
}
/* Limpa tudo na saída */
atexit(SDL_Quit);
/*
* Inicia o vídeo em um modo 640x480 usando uma paleta de 8-bits,
* requisitando uma surface de software
*/
screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "Não foi possível estabelecer o modo 640x480x8: %s\n", SDL_GetError());
exit(1);
}
Iniciando o Melhor Modo de Vídeo
Se você tiver preferência por uma certa profundidade de pixels mas aceitará qualquer outra, use SDL_SetVideoMode com SDL_ANYFORMAT como mostrado abaixo. Você também pode usar SDL_VideoModeOK() achar o modo de vídeo nativo que é mais próximo para o modo que você solicita.
Exemplo 2-2. Iniciando o Melhor Modo de Vídeo
/* Tem preferência por 8-bits, mas aceita qualquer outra profundidade */
screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE|SDL_ANYFORMAT);
if ( screen == NULL ) {
fprintf(stderr, "Não foi possível estabelecer o modo 640x480x8: %s\n", SDL_GetError());
exit(1);
}
printf("Estabelecendo o modo 640x480 a %d bits-por-pixel \n",
screen->format->BitsPerPixel);
Carregando e Mostrando um Arquivo BMP
A seguinte função carrega e mostra um arquivo BMP passado como parâmetro, desde que SDL esteja iniciada e o modo de vídeo tenha sido estabelecido.
Exemplo 2-3. Carregando e Mostrando um Arquivo BMP
void display_bmp(char *file_name)
{
SDL_Surface *image;
/* Carrega o arquivo BMP em uma surface */
image = SDL_LoadBMP(file_name);
if (image == NULL) {
fprintf(stderr, "Não pode carregar %s: %s\n", file_name, SDL_GetError());
return;
}
/*
* Modos de video paletizados, terão uma paleta padrão (um cubo
* padrão de 8*8*4 cores), mas se a imagem é paletizada também, nós podemos
* usar aquela paleta para um melhor ajuste de cor
*/
if (image->format->palette && screen->format->palette) {
SDL_SetColors(screen, image->format->palette->colors, 0, image->format->palette->ncolors);
}
/* Blita na surface de vídeo */
if(SDL_BlitSurface(image, NULL, screen, NULL) < 0)
fprintf(stderr, "Erro blitando surface: %s\n", SDL_GetError());
SDL_UpdateRect(screen, 0, 0, image->w, image->h);
/* Libera a surface BMP alocada */
SDL_FreeSurface(image);
}
Desenhando Diretamente para o Vídeo
As duas funções seguintes podem ser usadas para pegar e estabelecer pixels individuais em uma surface. Elas foram cuidadosamente escritas para trabalhar com qualquer profundidade atualmente suportada pela SDL. Lembre-se de travar a surface antes de chamá-las, e de destravá-las antes de chamar qualquer outra função da SDL.
Para converter entre valores de pixel e seus componentes vermelho, verde e azul, use SDL_GetRGB() e SDL_MapRGB().
Exemplo 2-4. getpixel()
/*
* Retorna o valor do pixel em (x, y)
* NOTA: A surface deve ser travada antes de chamar isto!
*/
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Aqui p é o endereço para o pixel que queremos recuperar */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *)p;
default:
return 0; /* não deve acontecer, mas evitamos as advertências */
}
}Exemplo 2-5. putpixel()
/*
* Fixa o pixel em (x, y) para o valor passado como parâmetro
* NOTA: A surface deve ser travada antes de chamar isto!
*/
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* Aqui p é o endereço para o ponteiro que queremos fixar */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}O seguinte código usa a função putpixel(), para colocar um pixel amarelo na metade do vídeo.
Exemplo 2-6. Usando putpixel()
/* Código para colocar um pixel amarelo no centro do vídeo */
int x, y;
Uint32 yellow;
/* Mapeia a cor amarela para este vídeo (R=0xff, G=0xFF, B=0x00)
Nota: Se o vídeo for paletizado, você deve estabelecer a paleta primeiro.
*/
yellow = SDL_MapRGB(screen->format, 0xff, 0xff, 0x00);
x = screen->w / 2;
y = screen->h / 2;
/* Trava a tela para acessar diretamente os pixels */
if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
fprintf(stderr, "Não pode travar a tela: %s\n", SDL_GetError());
return;
}
}
putpixel(screen, x, y, yellow);
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
/* Atualiza apenas a parte do vídeo que modificamos */
SDL_UpdateRect(screen, x, y, 1, 1);
return;