4. Imágenes transparentes
Curso: Introducción a los gráficos en C con SDL
4. Imágenes transparentes
Hemos visto cómo dibujar imágenes en pantalla, y cómo comprobar qué teclas se han pulsado, para hacer que una imagen se mueva sobre la otra.
Pero tenía un defecto, que hacía que no quedara vistoso: la imagen del "protagonista" tiene un recuadro negro alrededor, y al moverse sobreescribía el fondo, por lo que nunca se veían estrellas cerca de la nave.
Esto se debe evitar: una imagen que se mueve en pantalla (lo que se suele llamar un "sprite") debería tener zonas transparentes, a través de las que se vea el fondo.
Es algo fácil de conseguir con SDL: podemos hacer que un color se considere transparente, usando
SDL_SetColorKey(surface, SDL_SRCCOLORKEY,
SDL_MapRGB(surface->format, r, g, b));
donde "surface" es la superficie que queremos que tenga un color transparente (por ejemplo, nuestro protagonista), y "r, g, b" son las componentes roja, verde y azul del color que queremos que se considere transparente (si es el color negro el que queremos que no sea vea, serían 0,0,0).
Así, con nuestro protagonista haríamos
/* Preparamos las imagenes a mostrar */
fondo = SDL_LoadBMP("fondo.bmp");
protagonista = SDL_LoadBMP("protag.bmp");
/* El protagonista debe tener contorno transparente */
SDL_SetColorKey(protagonista, SDL_SRCCOLORKEY,
SDL_MapRGB(protagonista->format, 0, 0, 0));
Este es el único cambio necesario a nuestro programa para que no se borren los alrededores de la nave cuando se mueve.
El fuente quedaría
1: /*******************************************
2: * Introduccion a SDL - 4 *
3: * Curso de C, Nacho Cabanes *
4: *******************************************/
5:
6: #include <stdlib.h>
7: #include <SDL/SDL.h>
8:
9: int main(int argc, char *argv[])
10: {
11: SDL_Surface *screen;
12: SDL_Surface *fondo;
13: SDL_Surface *protagonista;
14: SDL_Rect destino;
15: int i, j;
16: int xProt = 320, yProt= 400;
17: int terminado = 0;
18: SDL_Event suceso;
19: Uint8* teclas;
20:
21:
22: /* Tratamos de inicializar la biblioteca SDL */
23: if (SDL_Init(SDL_INIT_VIDEO) < 0) {
24: printf("No se pudo inicializar SDL: %s\n", SDL_GetError());
25: exit(1);
26: }
27:
28: /* Preparamos las imagenes a mostrar */
29: fondo = SDL_LoadBMP("fondo.bmp");
30: protagonista = SDL_LoadBMP("protag.bmp");
31: /* El protagonista debe tener contorno transparente */
32: SDL_SetColorKey(protagonista, SDL_SRCCOLORKEY,
33: SDL_MapRGB(protagonista->format, 0, 0, 0));
34:
35: /* Si todo ha ido bien, hacemos algo:
36: entrar a modo grafico y cambiar el título de la ventana */
37: screen = SDL_SetVideoMode( 640, 480, 16, SDL_HWSURFACE );
38: if(screen == NULL) {
39: printf( "Error al entrar a modo grafico: %s\n", SDL_GetError() );
40: SDL_Quit();
41: return -1;
42: }
43:
44: /* Titulo de la ventana */
45: SDL_WM_SetCaption( "Hola mundo 4!", "Hola Mundo 4!" );
46:
47: /* Parte repetitiva: hasta que se elija terminar */
48: while(terminado == 0) {
49:
50: /* Dibujamos la imagen de fondo */
51: /* Como tiene 207 x 211 pixeles, la repetimos varias veces */
52: for (i=0; i<3; i++)
53: for (j=0; j<3; j++) {
54: destino.x=207*i;
55: destino.y=211*j;
56: SDL_BlitSurface(fondo, NULL, screen, &destino);
57: }
58:
59: /* Dibujamos el protagonista */
60: destino.x=xProt;
61: destino.y=yProt;
62: SDL_BlitSurface(protagonista, NULL, screen, &destino);
63:
64: /* Actualizamos la pantalla */
65: SDL_Flip(screen);
66:
67: /* Miramos si hay algun suceso pendiente,
68: entre ellos, peticion de abandonar el programa
69: (pulsar la X de la ventana) o tecla ESC */
70: while (SDL_PollEvent(&suceso)) {
71: if (suceso.type == SDL_QUIT) terminado = 1;
72: if (suceso.type == SDL_KEYDOWN)
73: if (suceso.key.keysym.sym == SDLK_ESCAPE) terminado = 1;
74: }
75:
76: /* Vemos el estado indivudal de las demas teclas */
77: teclas = SDL_GetKeyState(NULL);
78: if (teclas[SDLK_UP]) { yProt -= 2; }
79: if (teclas[SDLK_DOWN]) { yProt += 2; }
80: if (teclas[SDLK_LEFT]) { xProt -= 3; }
81: if (teclas[SDLK_RIGHT]) { xProt += 3; }
82:
83: /* Y esperamos 50 ms antes de repetir */
84: SDL_Delay( 50 );
85: }
86:
87: /* Finalmente, preparamos para salir */
88: SDL_Quit();
89: return 0;
90: }
y la apariencia sería:

Actualizado el: 31-05-2006 18:52