Este ejemplo esta completo, pero es la continuación de "El primer escenario", en el se han explicado muchas cosas que aquí ya pasaré por alto para centrarnos en el funcionamiento del scroll.
Programación
El archivo main.cpp contiene lo siguiente:
#include <allegro.h> #include "global.h" #include "players.h" #include "mijuego.h" void inicia_allegro() { allegro_init(); install_keyboard(); set_color_depth(32); set_gfx_mode(GFX_AUTODETECT_WINDOWED, PANTALLA_ANCHO, PANTALLA_ALTO, 0, 0); buffer = create_bitmap(PANTALLA_ANCHO, PANTALLA_ALTO); LOCK_VARIABLE(contador_tiempo_juego); LOCK_FUNCTION(inc_contador_tiempo_juego); // Iniciamos el limitador de FPS install_int_ex(inc_contador_tiempo_juego, BPS_TO_TIMER( FRAME_RATE )); } // programa principal int main() { inicia_allegro(); carga_juego(); salir = false; while ( !salir ) { if ( contador_tiempo_juego ) { while ( contador_tiempo_juego ) { actualiza_juego(); contador_tiempo_juego--; } clear_to_color(buffer, 0x00000); pinta_juego(); pintar_pantalla(); }else{ rest(1); } // tecla de salida if ( key[KEY_ESC] ) salir = true; } destroy_bitmap(buffer); return 0; } END_OF_MAIN();
El siguiente archivo es el global.h
/* GLOBAL.H */ // Ancho y alto de la pantalla const int PANTALLA_ANCHO = 800; const int PANTALLA_ALTO = 600; // En este BITMAP dibujaremos todo BITMAP *buffer; // es el espacio en pixel que recorre el jugador al andar const int desplazamiento=4; // Copiar el buffer a la pantalla del juego (screen) void pintar_pantalla() { blit(buffer, screen, 0, 0, 0, 0, PANTALLA_ANCHO, PANTALLA_ALTO); } // controla el bucle principal bool salir; // Variable usada para la velocidad volatile unsigned int contador_tiempo_juego = 0; const int FRAME_RATE = 30; // Función para controlar la velocidad void inc_contador_tiempo_juego() { contador_tiempo_juego++; } END_OF_FUNCTION(inc_contador_tiempo_juego)
El siguiente archivo es el player.h
// players.h // Esta clase se encarga del manejo del jugador class player { BITMAP *prota; int x,y; int direccion; int animacion; public: void inicia(); void pinta(); void teclado(); int getx(){ return x; }; int gety(){ return y; }; void posiciona( int _x, int _y); }; void player::inicia() { prota = load_bmp("personaje.bmp",NULL); // inicializar vbles direccion = 0; animacion = 0; x = 320; y = 280; } void player::pinta() { masked_blit(prota, buffer, animacion*32, direccion*32, x, y, 32,32); } void player::teclado() { int ax = x; int ay = y; // teclas control usuario if ( key[KEY_UP] ) { y-=desplazamiento; direccion = 3; } if ( key[KEY_DOWN] ) { y+=desplazamiento; direccion = 0; } if ( key[KEY_LEFT] ) { x-=desplazamiento; direccion = 1; } if ( key[KEY_RIGHT] ) { x+=desplazamiento; direccion = 2; } if ( ax != x || ay != y ) { // entra si a cambiado alguna de las variables x,y animacion++; if ( animacion > 2 ) animacion = 0; } // limites globales if ( x < 0 ) x = 0; if ( x > PANTALLA_ANCHO-32 ) x = PANTALLA_ANCHO-32; if ( y < 0 ) y = 0; if ( y > PANTALLA_ALTO-32 ) y = PANTALLA_ALTO-32; } void player::posiciona( int _x, int _y) { x=_x; y=_y; }
Estos tres códigos, están explicados en la entrada "El primer escenario". Si tienes algún problema no dudes en consultarlo.
A continuación el mas importante mijuego.h
/* mijuego.h */ BITMAP *bosq_a; BITMAP *bosq_b; BITMAP *bosq_c; BITMAP *UI; BITMAP *fondo; BITMAP *choque; BITMAP *cielo; player jugador; // indicará en que lugar estamos // 1: bosque int lugar; bool desplaza; int desplazamiento_map_x; int desplazamiento_map_y; // carga todo lo necesario antes de empezar el juego void carga_juego() { jugador.inicia(); bosq_a = load_bmp("b02.bmp",NULL); bosq_b = load_bmp("b03.bmp",NULL); bosq_c = load_bmp("b01.bmp",NULL); UI = load_bmp("t.bmp",NULL); // cargamos imagenes del primer escenario fondo = bosq_a; choque = bosq_c; cielo = bosq_b; lugar = 1; desplazamiento_map_x=0; desplazamiento_map_y=0; desplaza = true; } // actualiza el estado del juego void actualiza_juego() { int cambio = 0; int ax,ay; ax = jugador.getx(); ay = jugador.gety(); if ( desplaza ) { int d = desplazamiento / 2; // controla el desplazamiento del mapa si esta en los bordes if ( ax < 160 && desplazamiento_map_x > 0 ) { desplazamiento_map_x-=d; jugador.posiciona(ax+d,ay); ax = jugador.getx(); ay = jugador.gety(); if ( ax < 60 && desplazamiento_map_x > 0 ) { desplazamiento_map_x-=d; jugador.posiciona(ax+d,ay); } } if ( ay < 160 && desplazamiento_map_y > 0 ) { desplazamiento_map_y-=d; jugador.posiciona(ax,ay+d); ax = jugador.getx(); ay = jugador.gety(); if ( ay < 60 && desplazamiento_map_y > 0 ) { desplazamiento_map_y-=d; jugador.posiciona(ax,ay+d); } } if ( ax > PANTALLA_ANCHO-160 && desplazamiento_map_x < fondo->w-PANTALLA_ANCHO ) { desplazamiento_map_x+=d; jugador.posiciona(ax-d,ay); ax = jugador.getx(); ay = jugador.gety(); if ( ax > PANTALLA_ANCHO-60 && desplazamiento_map_x < fondo->w-PANTALLA_ANCHO ) { desplazamiento_map_x+=d; jugador.posiciona(ax-d,ay); } } if ( ay > PANTALLA_ALTO-160 && desplazamiento_map_y < fondo->h-PANTALLA_ALTO ) { desplazamiento_map_y+=d; jugador.posiciona(ax,ay-d); ax = jugador.getx(); ay = jugador.gety(); if ( ay > PANTALLA_ALTO-60 && desplazamiento_map_y < fondo->h-PANTALLA_ALTO ) { desplazamiento_map_y+=d; jugador.posiciona(ax,ay-d); } } ax = jugador.getx(); ay = jugador.gety(); } jugador.teclado(); // comprobar si colisiona con el mapa bool choca = false; int px = jugador.getx()+desplazamiento_map_x; int py = jugador.gety()+16+desplazamiento_map_y; for ( int ci=2; ci < 30; ci++) { for (int cj=0; cj < 16; cj++) { // color rojo if ( getpixel( choque, px+ci, py+cj) == 0xff0000 ){ choca = true; } // color verde if ( getpixel( choque, px+ci, py+cj) == 0x00ff00 ) cambio = 1; // color azul if ( getpixel( choque, px+ci, py+cj) == 0x0000ff ) cambio = 2; // color amarillo if ( getpixel( choque, px+ci, py+cj) == 0xffff00 ) cambio = 3; // color celeste if ( getpixel( choque, px+ci, py+cj) == 0x00ffff ) cambio = 4; // otro azul 0080ff if ( getpixel( choque, px+ci, py+cj) == 0x0080ff ) cambio = 5; // naranja if ( getpixel( choque, px+ci, py+cj) == 0xff8000 ) cambio = 6; } } if ( choca ){ // vuelve al estado anterior jugador.posiciona( ax,ay ); } switch ( lugar ) { case 1: if ( cambio == 1 ) { // 1000,540 jugador.posiciona( 400,540 ); desplazamiento_map_x = 600; } if ( cambio == 2 ) { // 610,100 jugador.posiciona( 400,100 ); desplazamiento_map_x = 210; } if ( cambio == 3 ) { jugador.posiciona( 420,460 ); desplazamiento_map_x = 0; } if ( cambio == 4 ) { // 1400,350 jugador.posiciona( 700,350 ); desplazamiento_map_x = 700; } if ( cambio == 5 ) { jugador.posiciona( 70,250 ); desplazamiento_map_x = 0; } if ( cambio == 6 ) { jugador.posiciona( 290,100 ); desplazamiento_map_x = 0; } break; default: break; } } // Se encarga de pintar todo sobre el buffer void pinta_juego() { int ancho, alto; int ax=0; int ay=0; int bx=0; int by=0; switch ( lugar ) { case 1: ax = desplazamiento_map_x; ay = desplazamiento_map_y; ancho = PANTALLA_ANCHO; alto = PANTALLA_ALTO; break; default: break; } blit( fondo, buffer, ax, ay, bx, by, ancho, alto); jugador.pinta(); masked_blit( cielo, buffer, ax, ay, bx, by, ancho, alto); masked_blit( UI, buffer, 0, 0, 0, 0, ancho, alto); }
Al principio se declaran las variables de las imágenes que se van a utilizar, en este caso bosq_a, bosq_b, bosq_c, UI, fondo, choque y cielo. Se declara la variable desplaza que es la que indicará que el escenario tiene scroll, para este desplazamiento del escenario se utilizan las variables desplazamiento_map_x y desplazamiento_map_y.
La función carga_juego() se encarga de cargar todas las imágenes necesarias, inicializa las variables necesarias para un correcto funcionamiento.
La función actualiza_juego(), aquí es donde se controla el scroll del mapa comprobando previamente que desplaza sea true. Se controla el desplazamiento del mapa cuando el personaje llega al borde de la ventana. Hay que tener en cuenta de que el jugador esta posicionado según el tamaño de la ventana, es decir, tendrá un valor entre el 0,0 y el 800,600.
También actualiza la posición del jugador y comprueba si choca con el escenario.
Como la posición del jugador no es absoluta con respecto al escenario antes de comprobar el pixel de choque debe calcularse la posición absoluta px,py. Para ello se obtiene la posición del jugador con respecto a la ventana y se le añade el desplazamiento del mapa según el eje que corresponda.
A continuación se comprueba el color y se le da un valor a la variable cambio. Después de comprueba que valor tiene cambio y según su valor posiciona al jugador a una nueva posición. De esta forma haremos que nuestro personaje se desplace a otro mapa o a una nueva posición según deseemos.
La función pinta_juego(), se encarga de pintar el fondo, pinta el personaje, la imagen cielo y la imagen UI.
Las imágenes utilizada para el juego se encuentra en la sección de descarga, o puede descargarlas haciendo click aqui
En este video se muestra el funcionamiento del código, vemos como el personaje al acercarse al borde de la pantalla se inicia el scroll, es decir, el movimiento del escenario.
esta genial, te sigo desde el blog antiguo, me gustaría que a tu juego le pusieras: objetos(cascos, espadas, armaduras,etc..) y que halla una interfaz de inventario, donde puedas usar los botones del mouse(para arrastrar y mover tus objetos).
ResponderEliminarEso ya esta hecho, mira el siguiente video:
Eliminarhttps://www.youtube.com/watch?v=j6tVvif8rzQ
Para hacerlo entra en el apartado dedicado al inventario :
http://devcpp-allegro.blogspot.com.es/2015/10/crear-juego-rpg-en-c-y-allegro-4-20.html
http://devcpp-allegro.blogspot.com.es/2015/10/crear-juego-rpg-en-c-y-allegro-4-21.html
oye, puedes subir el proyecto completo? es dificil seguir tu tutorial si no se tiene el codigo completo o no se explica bien...
ResponderEliminarConcretamente este tutorial tiene el codigo completo, de los 4 archivos que lleva. Solo tienes que copiar y pegar.
EliminarHola amigo, te sigo desde el blog pasado, estaría increíble que subieras todos los recursos que utilizaste en tu blog anterior
ResponderEliminarCuando usas bosq_ y cargas las imagenes b02, b03 y b01.bmp entiendo que cargas fondo, cielo y choque, ¿pero que imagen quieres cargar con t.bmp?
ResponderEliminarEsa imagen se utiliza para la interfaz del usuario, una imagen que se mostrará por encima de todo. Que se puede utilizar para mostrar datos del jugador ( vida, etc.)
Eliminargracias por tu aporte, lo valoro mucho bro, de corazon y ojala lo puedas continuar, muchas gracias nuevamente!
ResponderEliminar