SDL en C bajo GNU/Linux 004 – Varias imágenes y animación


 
Mostrar una imagen fue lo que vimos en el anterior post sobre SDL en C bajo GNU/Linux. En esta ocasión vamos a mostrar 2 imágenes. Una de fondo y otra que es un sprite con el que vamos a jugar para crear una animación de una persona andando.
 
 
Para que no tengas que picar mucho código y crear estructuras de directorios he empaquetado en un zip todo el tinglado: mostrarimagen.zip
 
 
Descargando ese zip no tendréis que andar bajando nada, no obstante voy a colocar las 2 imágenes que necesitaremos:
 
 

 
 

 
 
Si has descargado el zip y lo has descomprimido podrás compilar el código ejecutando make en el directorio en el que se encuentra mostrarimagen.c (directorio en el que estará también el makefile).
 
 
Se que no es común encontrar un bmp transparente pero … es posible crear bmps con fondo transparente y por eso quería probar si con SDL se podría jugar un poco y animar un sprite.
He bajado un sprite del juego Day of the tentacle. El sprite es basicamente una secuencia de los diferentes frames que podemos usar para que parezca que el personaje está andando. En este caso son 6.
 
 
Para saber cuanto tiene de ancho un frame de ese sprite tenemos que dividir entre 6 el ancho total
 
 

 
 
Dejo aquí el código para ver si se entiende lo realizado:
 
 

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

int main(void) {
	SDL_Window * ventana;
	SDL_Renderer * render;

	SDL_Surface * imagenEscenario;		// Escenario
	SDL_Texture * texturaEscenario;		// Escenario
	SDL_Surface * imagenPersonaje;          // Personaje
	SDL_Texture * texturaPersonaje;         // Personaje
	int x = 0;
	int y = 324;				// 480  de alto del escenario - 112 del alto del personaje son 324.
	int s = 20;				// los pixeles que avanzará el personae a cada paso.
	int alturaPersonaje = 112;		// la altura del frame del personaje.
	int anchuraPersonaje = 156;		// la anchura del frame del personaje.

        SDL_Rect srcrect1 = { 0, 0, alturaPersonaje, anchuraPersonaje };	// frame1 del personaje
        SDL_Rect srcrect2 = { 112, 0, alturaPersonaje, anchuraPersonaje };	// frame2 del personaje
        SDL_Rect srcrect3 = { 224, 0, alturaPersonaje, anchuraPersonaje };	// frame3 del personaje
        SDL_Rect srcrect4 = { 336, 0, alturaPersonaje, anchuraPersonaje };	// frame4 del personaje
        SDL_Rect srcrect5 = { 448, 0, alturaPersonaje, anchuraPersonaje };	// frame5 del personaje
        SDL_Rect srcrect6 = { 560, 0, alturaPersonaje, anchuraPersonaje };	// frame6 del personaje

        imagenEscenario = SDL_LoadBMP("res/escenario.bmp");	// Cargamos el bmp del escenario. El fondo.
        imagenPersonaje = SDL_LoadBMP("res/personaje.bmp");	// Cargamos el sprite para extraer todos los frames


        SDL_Init(SDL_INIT_VIDEO);
        ventana = SDL_CreateWindow("mostrando una imagen",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL);
        if (ventana == NULL) {
                printf("No se pudo crear la ventana: %s\n", SDL_GetError());
                return 1;
        }

        render = SDL_CreateRenderer(ventana, -1, 0);

        texturaEscenario = SDL_CreateTextureFromSurface(render, imagenEscenario);
        texturaPersonaje = SDL_CreateTextureFromSurface(render, imagenPersonaje);


	// Cargamos el escenario
	SDL_RenderCopy(render, texturaEscenario, NULL, NULL);
	SDL_RenderPresent(render);

	// Cargamos el personaje en el frame 1
        SDL_Rect dstrect1 = { x, y, alturaPersonaje, anchuraPersonaje };
	SDL_RenderCopy(render, texturaPersonaje, &srcrect1, &dstrect1);
	SDL_RenderPresent(render);

        SDL_Delay(250);

	// Cargamos el personaje en el frame 2
        SDL_RenderCopy(render, texturaEscenario, NULL, NULL);
        SDL_RenderPresent(render);
        x = x+s;
        SDL_Rect dstrect2 = { x, y, alturaPersonaje, anchuraPersonaje };
        SDL_RenderCopy(render, texturaPersonaje, &srcrect2, &dstrect2);
        SDL_RenderPresent(render);

        SDL_Delay(250);

	// Cargamos el personaje en el frame 3
        SDL_RenderCopy(render, texturaEscenario, NULL, NULL);
        SDL_RenderPresent(render);
        x = x+s;
        SDL_Rect dstrect3 = { x, y, alturaPersonaje, anchuraPersonaje };
        SDL_RenderCopy(render, texturaPersonaje, &srcrect3, &dstrect3);
        SDL_RenderPresent(render);

        SDL_Delay(250);

	// Cargamos el personaje en el frame 4
        SDL_RenderCopy(render, texturaEscenario, NULL, NULL);
        SDL_RenderPresent(render);
        x = x+s;
        SDL_Rect dstrect4 = { x, y, alturaPersonaje, anchuraPersonaje };
        SDL_RenderCopy(render, texturaPersonaje, &srcrect4, &dstrect4);
        SDL_RenderPresent(render);

        SDL_Delay(250);

	// Cargamos el personaje en el frame5
        SDL_RenderCopy(render, texturaEscenario, NULL, NULL);
        SDL_RenderPresent(render);
        x = x+s;
        SDL_Rect dstrect5 = { x, y, alturaPersonaje, anchuraPersonaje };
        SDL_RenderCopy(render, texturaPersonaje, &srcrect5, &dstrect5);
        SDL_RenderPresent(render);

        SDL_Delay(250);

	// Cargamos el personaje en el frame6
        SDL_RenderCopy(render, texturaEscenario, NULL, NULL);
        SDL_RenderPresent(render);
        x = x+s;
        SDL_Rect dstrect6 = { x, y, alturaPersonaje, anchuraPersonaje };
        SDL_RenderCopy(render, texturaPersonaje, &srcrect6, &dstrect6);
        SDL_RenderPresent(render);

        SDL_Delay(3000);


	SDL_DestroyTexture(texturaEscenario);
	SDL_FreeSurface(imagenEscenario);
        SDL_DestroyTexture(texturaPersonaje);
        SDL_FreeSurface(imagenPersonaje);

	SDL_DestroyRenderer(render);
	SDL_DestroyWindow(ventana);

        SDL_Quit();
        return 0;
}

 
 

Para que se entienda mejor y no tener que añadir código de control de eventos he ido poniendo cada frame con una espera de 250ms (un cuarto de segundo) seguidos. Se puede ver en el código todo lo que ya hemos visto en anteriores artículos.
 
 

 
 
Lo nuevo es que en vez de una imagen vemos que podemos añadir una sobre otra. Por ejemplo si fuéramos mala gente seguramente quedriamos crearnos un programa que añadiese una mascara de agua a una foto. pues con esto ya sabríamos hacerlo (al menos para sobreponer 2 imágenes). Para guardar se necesitarían otras funciones.
 
 
Esto no incorpora mucho más a lo que ya hemos visto, no obstante es bueno saber que podemos coger solamente una parte de un mapa de bits y mostrarla donde queramos. Es por eso que quería realizar este ejemplo.
 
 
Para no liar demasiado en vez de crear un bucle he preferido simplemente colocarlo todo secuencialmente.
 
 
Es bueno darse también cuenta de que en un programa de verdad tendríamos que estar ya realizando funciones y trabajar en diferentes archivos para que fuese algo más modular y reutilizable.
 
 
Pero no son programas de verdad, de momento son ejemplos para ir viendo que cosas se pueden hacer con SDL programando en C sobre GNU/Linux.
 
 
Saludos cordiales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *