martes, 5 de octubre de 2021

Efecto espejo

 


El ejemplo que se va hacer trata de recrear el efecto espejo en C++ y Allegro 5, concretamente tal y como se ve en el siguiente video.




En el ejemplo que muestra el video tiene dos espejos, uno grande en el lateral derecho y otro mas pequeño en el muro de arriba.

Para crear el efecto de espejo pequeño se realizan dos tareas:

  • Por un lado se crea una copia del suelo que se va a reflejar en el espejo, y esta imagen se voltea de forma vertical.
  • Y por otro lado se crea la imagen reflejo del personaje. Esta imagen es la misma del personaje pero con las direcciones invertidas. Además la imagen reflejo esta volteada de forma horizontal.

Para crear el efecto de espejo grande es mas sencillo, pues toma una copia de toda la imagen que se quiere reflejar y esta imagen se voltea de forma horizontal.

Para un correcto funcionamiento el orden de poner los espejos es primero el pequeño, y luego el grande lateral.


		al_set_target_bitmap(espejo2);

		al_draw_bitmap_region(buffer, 65, 138, 350, 90, 0, 0, ALLEGRO_FLIP_VERTICAL);
		
		// invertir direccion para el personaje espejo
		if (dir == 3) dirEsp = 0;
		if (dir == 0) dirEsp = 3;
		if (dir == 1) dirEsp = 2;
		if (dir == 2) dirEsp = 1;

		al_draw_bitmap_region(personaje, paso * 48, dirEsp * 48, 48, 48, x - 65, 135 - y, ALLEGRO_FLIP_HORIZONTAL);


Este código se encarga del primer espejo, el pequeño. En la primera línea se establece la imagen espejo2 como el bitmap con el que vamos a trabajar, todas las instrucciones que se realicen con imágenes se realizaran sobre la imagen espejo2.

En la segunda línea se crea una copia de la imagen buffer, exactamente una región que viene delimitada por la coordenada de inicio (65,138) y por un tamaño (350 de ancho y 90 de alto). Y esta imagen se pega en espejo2 en la coordenada (0,0), y según el flag indicado la imagen estará volteada de forma vertical.

Las siguientes líneas se encargan de invertir la dirección del personaje espejo, y es almacenada en la variable dirEsp.

En la última línea se dibuja el personaje invertido volteado de forma horizontal sobre la imagen espejo2.  Llegado a este punto la imagen espejo2 contiene toda la imagen que se va a mostrar del espejo pequeño.


		al_set_target_bitmap(buffer2);

		al_draw_bitmap_region(buffer, 100, 0, 350, 600, 0, 0, ALLEGRO_FLIP_HORIZONTAL);

		al_set_target_bitmap(buffer);

		al_draw_tinted_bitmap_region(buffer2, al_map_rgba_f(1, 1, 1, .9), 0, 0, 350, 600, 449, 0, 0);


Con el primer comando, indicamos que se va a trabajar con la imagen buffer2, esta imagen contendrá la imagen reflejo del espejo grande.

Con el segundo comando se realiza una copia del contenido de la imagen buffer, partiendo de la posición (100,0), con un tamaño de 350 de ancho y 600 de alto. Y se pega en la imagen buffer2 en la posición (0,0) volteada de forma horizontal.

Luego se vuelve a indicar que se trabaja con la imagen buffer. Y con el último comando se pega el contenido de buffer2 sobre buffer, partiendo de la posición (0,0), con un tamaño de 350 de ancho y 600 de alto, en la posición (449,0), tintado con un 0.9 de transparencia.

El Código

/*
  Name:		Efecto Espejo
  Author:   Yadok - KODAYGAMES
  Date:     05/10/21
  Web:      http://devcpp-allegro.blogspot.com/
*/

#define FPS    60
// pixeles que se desplaza por segundo
#define Velocidad 180

int main()
{
	al_init();
	al_install_keyboard();
	if (!al_init_image_addon())
	{		
		return -1;
	}

	ALLEGRO_DISPLAY* pantalla = al_create_display(800, 600);

	ALLEGRO_BITMAP* buffer = al_create_bitmap(800, 600);
	ALLEGRO_BITMAP* buffer2 = al_create_bitmap(350, 600);
	ALLEGRO_BITMAP* espejo2 = al_create_bitmap(350, 90);

	ALLEGRO_BITMAP* fondo = al_load_bitmap("fondo.png");
	ALLEGRO_BITMAP* espejo = al_load_bitmap("frontales.png");

	al_set_window_title(pantalla, "Efecto Espejo");

	al_clear_to_color(al_map_rgb(125, 155, 225));

	ALLEGRO_BITMAP* personaje = al_load_bitmap("chica.png");

	ALLEGRO_KEYBOARD_STATE teclado;

	// defino lista de eventos
	ALLEGRO_EVENT_QUEUE* Mis_eventos;
	ALLEGRO_EVENT evento;

	bool salir;
	bool pas = false;
	int x, y;
	int paso = 0;
	int dir = 0;
	int dirEsp = 3;

	int desplazamiento = Velocidad / FPS;

	// inicializar vbles
	x = 50;
	y = 200;

	salir = false;

	// creo lista de eventos
	Mis_eventos = al_create_event_queue();

	// asigno eventos a la lista de eventos
	al_register_event_source(Mis_eventos, al_get_keyboard_event_source());
	al_register_event_source(Mis_eventos, al_get_display_event_source(pantalla));

	while (!salir)
	{
		al_set_target_bitmap(buffer);
		al_clear_to_color(al_map_rgb(125, 155, 225));
		al_draw_bitmap(fondo, 0, 0, 0);
		
		if (x > 400) x = 400;
		if (x < 0) x = 0;
		if (y < 100) y = 100;
		if (y > 550) y = 550;

		al_set_target_bitmap(espejo2);

		al_draw_bitmap_region(buffer, 65, 138, 350, 90, 0, 0, ALLEGRO_FLIP_VERTICAL);
		
		// invertir direccion para el personaje espejo
		if (dir == 3) dirEsp = 0;
		if (dir == 0) dirEsp = 3;
		if (dir == 1) dirEsp = 2;
		if (dir == 2) dirEsp = 1;

		al_draw_bitmap_region(personaje, paso * 48, dirEsp * 48, 48, 48, x - 65, 135 - y, ALLEGRO_FLIP_HORIZONTAL);

		al_set_target_bitmap(buffer);

		al_draw_tinted_bitmap_region(espejo2, al_map_rgba_f(.9, .9, 1, 1), 0, 0, 350, 90, 65, 30, 0);

		al_set_blender(ALLEGRO_ADD, ALLEGRO_ZERO, ALLEGRO_INVERSE_ALPHA );

		// sombra
		al_draw_tinted_bitmap_region(personaje, al_map_rgba_f(1, 1, 1, 0.25), paso * 48, dir * 48, 48, 48, x, y+44 , ALLEGRO_FLIP_VERTICAL);

		al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
		
		al_draw_bitmap_region(personaje, paso * 48, dir * 48, 48, 48, x, y, 0);

		al_set_target_bitmap(buffer2);

		al_draw_bitmap_region(buffer, 100, 0, 350, 600, 0, 0, ALLEGRO_FLIP_HORIZONTAL);

		al_set_target_bitmap(buffer);

		al_draw_tinted_bitmap_region(buffer2, al_map_rgba_f(1, 1, 1, .9), 0, 0, 350, 600, 449, 0, 0);

		al_set_target_backbuffer(pantalla);

		al_draw_bitmap(buffer, 0, 0, 0);

		al_draw_bitmap(espejo, 0, 0, 0);
	
		al_flip_display();


		al_wait_for_event_timed(Mis_eventos, &evento, 1.0 / FPS);

		// se ha cerrado la ventana
		if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
		{
			salir = true;
		}

		pas = false;

		// se ha pulsado una tecla
		if (evento.type == ALLEGRO_EVENT_KEY_DOWN)
		{			
			if (evento.keyboard.keycode == ALLEGRO_KEY_W || evento.keyboard.keycode == ALLEGRO_KEY_UP) {
				pas = true;
				dir = 3;
			}
			if (evento.keyboard.keycode == ALLEGRO_KEY_S || evento.keyboard.keycode == ALLEGRO_KEY_DOWN) {
				pas = true;
				dir = 0;
			}
			if (evento.keyboard.keycode == ALLEGRO_KEY_A || evento.keyboard.keycode == ALLEGRO_KEY_LEFT) {
				pas = true;
				dir = 1;
			}
			if (evento.keyboard.keycode == ALLEGRO_KEY_D || evento.keyboard.keycode == ALLEGRO_KEY_RIGHT) {
				pas = true;
				dir = 2;
			}
			if (evento.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
				salir = true;
			}
		}

		al_get_keyboard_state(&teclado);

		if (al_key_down(&teclado, ALLEGRO_KEY_W) || al_key_down(&teclado, ALLEGRO_KEY_UP))
		{
			pas = true;
			y= y - desplazamiento;
		}
		if (al_key_down(&teclado, ALLEGRO_KEY_S) || al_key_down(&teclado, ALLEGRO_KEY_DOWN))
		{
			pas = true;
			y= y + desplazamiento;
		}
		if (al_key_down(&teclado, ALLEGRO_KEY_A) || al_key_down(&teclado, ALLEGRO_KEY_LEFT))
		{
			pas = true;
			x= x - desplazamiento;
		}
		if (al_key_down(&teclado, ALLEGRO_KEY_D) || al_key_down(&teclado, ALLEGRO_KEY_RIGHT))
		{
			pas = true;
			x= x + desplazamiento;
		}

		if (pas)
		{
			paso++;
			if (paso > 2) paso = 0;
		}
		
	}

	// liberar recursos utilizados
	al_destroy_bitmap(fondo);
	al_destroy_bitmap(buffer);
	al_destroy_bitmap(buffer2);
	al_destroy_bitmap(espejo);
	al_destroy_bitmap(espejo2);
	al_destroy_bitmap(personaje);
	al_destroy_event_queue(Mis_eventos);
	al_destroy_display(pantalla);

	return 0;
}


A este código solo le falta incluir las librerías, allegro5/allegro.h y allegro5/allegro_image.h, que se deben de poner al principio del código antes de los #define.

Este programa, inicializa la librería allegro, y carga las imagenes que va a utilizar: fondo.png, frontales.png y chica.png.

El bucle principal se estará repitiendo mientras salir sea false. Al principio todo con respecto a las imágenes se realiza sobre la imagen llamada buffer, y al final se muestra por pantalla. El funcionamiento principal del código es igual al ejemplo de las transparencias.

Para finalizar el programa puedes pulsar la tecla ESC o pulsar sobre la X de la ventana.

El manejo del personaje se puede realizar mediante las teclas de las flechas del cursor o las teclas W,A,S,D.  

Al finalizar el programa elimina todas las imágenes utilizadas. 

Si deseas el código completo y las imágenes utilizadas descarga el archivo ZIP haciendo clic aquí.

No hay comentarios:

Publicar un comentario

Antes de publicar un comentario

Todos los comentarios que se realicen en el blog son moderados.

Debido a esto es muy probable que tu comentario no aparezca de inmediato ya que previamente debe ser revisado para evitar un mal uso (SPAM).

Podrán realizar comentario cualquiera que tenga una cuenta de Google.

Related Posts Plugin for WordPress, Blogger...