sábado, 31 de octubre de 2015

Crear juego RPG en C++ y Allegro 4 (28) Menu II

Aquí esta una nueva entrega del curso crea tu juego RPG en C++ y Allegro. Continuamos con el menu.







Ya solo nos queda actualizar el archivo mijuego.h.

Se crea una nueva función llamada carga_inicio(), que contiene la carga de los ficheros .DAT, la lectura de los objetos y las imagenes del menú.

void carga_inicio()
{
    packfile_password(evalc);
    
    datosjuego = load_datafile("datosjuego.dat");
    if ( !datosjuego ){
       allegro_message("Error: archivo datosjuego.dat no encontrado\n%s\n", allegro_error);       
    }  
    
    datobjetos = load_datafile("objetos.dat");
    if ( !datobjetos ){
       allegro_message("Error: archivo objetos.dat no encontrado\n%s\n", allegro_error);       
    }     
    
    datotiendas = load_datafile("datostienda.dat");
    if ( !datobjetos ){
       allegro_message("Error: archivo datostienda.dat no encontrado\n%s\n", allegro_error);       
    }    
    
    lee_objetos(); 
    

    menufondo = (BITMAP *)datosjuego[dimenu].dat;  
    menufondo2 = (BITMAP *)datosjuego[dimenu2].dat;             
}

Se crea una función para actualizar el contenido de la variable cbuffer, que contendrá el mapa de choque de lo que se muestra por pantalla, que se llama carga_mapa_choque().

void carga_mapa_choque()
{
    clear_to_color( cbuffer, makecol(0, 0, 0));       
    blit ( choque, cbuffer, desplazamiento_map_x, desplazamiento_map_y,0,0, PANTALLA_ANCHO, PANTALLA_ALTO); 
    jugador.pon_choque();     
}

Se reduce el contenido de la función carga_juego(), ya que parte de lo que tenía se ha trasladado a la función carga_inicio().

void carga_juego()
{ 
    cambio = 0;
    carga_escenario();

    dialogo.crea("", (FONT *)datosjuego[dftextos].dat, 10, PANTALLA_ALTO-100, PANTALLA_ANCHO-10, PANTALLA_ALTO-10);  
    hablando = 0; 
    
    mision = 1;
    swraton=-1;
       
    swinv=0;
    muestra_tienda = false;
    swtienda=0;
}

Se realizan algunos cambios en la función carga_escenario().

// carga los datos del escenario segun lugar
void carga_escenario()
{ 
    switch ( lugar ) 
    {           
    case 1:// casa
              fondo  = (BITMAP *)datosjuego[dicasa].dat;
              choque = (BITMAP *)datosjuego[dicasachoque].dat;
              cielo  = (BITMAP *)datosjuego[dicasasup].dat;  
               
              carga_mapa_choque(); 
              desplaza = false;
              if ( cambio != 0 ) sonido_abrirpuerta();  
              musica_casa();  
         break;
          
    case 2:// bosque
              fondo  = (BITMAP *)datosjuego[dibosque].dat;
              choque = (BITMAP *)datosjuego[dibosquechoque].dat;
              cielo  = (BITMAP *)datosjuego[dibosquesup].dat;              
 
              desplaza=true;     
              carga_mapa_choque(); 
              sonido_ambiente();
              musica_bosque();
         break;
          
    case 3:// ciudad
              fondo  = (BITMAP *)datosjuego[dicity1].dat;
              choque = (BITMAP *)datosjuego[dicity1choque].dat;
              cielo  = (BITMAP *)datosjuego[dicity1sup].dat;              
 
              desplaza=true;   
              carga_mapa_choque();
              if ( cambio == 0 ) musica_ciudad1();   
         break;
    case 4:// tienda1
              fondo  = (BITMAP *)datosjuego[ditienda1].dat;
              choque = (BITMAP *)datosjuego[ditienda1choque].dat;
              cielo  = (BITMAP *)datosjuego[ditienda1sup].dat;  
              carga_mapa_choque();
              desplaza=false;
              if ( cambio != 0 ) sonido_abrirpuerta(); 
              if ( cambio == 0 ) musica_ciudad1();
         break;                               
    }         
}

En la función cambia_escenario(), se suprime algunos sonidos, y se añade la llamada a la función carga_mapa_choque().

void cambia_escenario()
{
    
    switch ( lugar ) 
    {           
    case 1:   // casa
         if ( cambio == 1 )
         {
              // cambiamos a otro lugar  
              // bosque             
              lugar = 2;
              carga_escenario();
              // situamos al prota dentro de la casa
              jugador.posiciona( 410,370 ); 
              desplazamiento_map_x=0;
              desplazamiento_map_y=160; 
              cambio = 0;

           
         }
         break;
    case 2:   // bosque
         if ( cambio == 2 )
         {
              // cambiamos a otro lugar
              // casa
              lugar = 1;
              carga_escenario();
              // situamos al prota cerca de la puerta
              jugador.posiciona( 290,440 ); 
              desplazamiento_map_x=-160;
              desplazamiento_map_y=-160;  
              sonido_abrirpuerta(); 
              para_sonido_ambiente();   
              cambio = 0;
            
         }
         if ( cambio == 3 )
         {
              // cambiamos a otro lugar
              // ciudad
              lugar = 3;
              carga_escenario();
              // situamos al prota en el camino 
              jugador.posiciona( 500,540 ); 
              desplazamiento_map_x=950;
              desplazamiento_map_y=508;   
              para_sonido_ambiente(); 
              musica_ciudad1();  
              cambio = 0;   
         }         
         break;  
    case 3:   // ciudad
         if ( cambio == 1 )
         {
              // cambiamos a otro lugar
              // bosque             
              lugar = 2;
              carga_escenario();     
              // situamos al prota en el camino del bosque        
              jugador.posiciona( 650,30 ); 
              desplazamiento_map_x=200;
              desplazamiento_map_y=0; 
              cambio = 0;
         }
         // color amarillo que existen muchos
         if ( cambio == 3 && desplazamiento_map_x > 800 )
         {
              // cambiamos a otro lugar
              // tienda1            
              lugar = 4;
              carga_escenario();     
              // situamos al prota en el camino del bosque        
              jugador.posiciona( 376,460 ); 
              desplazamiento_map_x=-170;
              desplazamiento_map_y=-100; 
  
              cambio = 0;
         }         
         break;   
    case 4:   // tienda1
         if ( cambio == 1)
         {
              // cambiamos a la ciudad
              lugar=3;
              carga_escenario();
              jugador.posiciona( 400,300 );
              desplazamiento_map_x=1090;
              desplazamiento_map_y=85; 
              cambio = 0;    
              sonido_abrirpuerta();         
         }    
              
                
    default:
         break;
    }       
    carga_mapa_choque();    
}

Se realizan algunos cambios en la función pinta_juego().

// 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:   // casa     
             bx=160;
             by=160; 
             ancho = 480;
             alto = 325;
             break;
    case 2:   // bosque 
             ax = desplazamiento_map_x; 
             ay = desplazamiento_map_y;
             ancho = PANTALLA_ANCHO;
             alto  = PANTALLA_ALTO;
             break;
    case 3:  // ciudad1
             ax = desplazamiento_map_x; 
             ay = desplazamiento_map_y;
             ancho = PANTALLA_ANCHO;
             alto  = PANTALLA_ALTO;  
             break;
  case 4: // tienda1
             bx = 170;   
             by = 100;
             ancho = 448;
             alto = 416;      
             break;                                        
    default:
         break;
    }  


    blit( fondo, buffer, ax, ay, bx, by, ancho, alto);
    for ( int z=0; z < npersonaje; z++ )
    {
         personajes[z].pinta();
    }
    
    for ( int z=0; z < nmalos; z++ )
    {         
        malos[z].pinta();
    }
              
    jugador.pinta();  
       
    masked_blit( cielo, buffer, ax, ay, bx, by, ancho, alto); 
    
    if ( hablando > 1 )
    {
         dialogo.pinta(buffer);
         hablando++;
    }   
    
    pinta_barra_vida();
    pinta_lvlup();
    pinta_inventario();    
    
    pinta_tienda();
}   

Y llegado a este punto ya estaría todos los cambios realizados en el archivo mijuego.h.

Haz clic aqui para descargar en RAR el archivo mijuego.h

Para que todo vaya correctamente debe de tener los siguientes archivos:

Archivo datosjuego.dat  y datosjuego.h, que contienen imagenes, sonidos, etc. Descargar
Archivos de los objetos y la tienda, que incluye objetos.dat, objetos.txt, datostienda.dat, tiendas.txt, list01.txt y list02.txt. Descargar


Y si todo esta correcto debes tener algo similar a lo que se muestra en el siguiente video.


3 comentarios:

  1. Disculpa, para poder cambiar de imagen de fondo al presionar cierta tecla , cómo lo podría hacer?

    ResponderEliminar
    Respuestas
    1. if ( key[KEY_1] )
      {
      blit( otro, buffer, 0, 0, 0, 0, 800, 600);
      }

      Con este codigo, estamos indicando que cuando se pulse la tecla 1, se pinte la imagen otro sobre el buffer, que es la variable que habitualmente utilizamos para pintar antes de mostrar por pantalla, en este ejemplo presupongo que la imagen es de 800x600. Para que esto funcione, tienes que ponerlo justamente despues de donde pintas el fondo, de esta manera cuando se pulse el 1 el fondo será sustituido por el contenido de la imagen otro.

      Eliminar
  2. Hola.

    Al compilar el proyecto en este capítulo, a mi me apareció un error en la compilación porque la función itoa no es estándar en C++. Lo solucioné creando mi propia función itoa. Les adjunto el código por si a alguien le sive.


    Función itoa: convierte un entero a una cadena (función NO estándar de C y C++).

    En partidas.h implementamos el siguiente código, al inicio.

    Primero, creamos una función para invertir una cadena (string)

    // Función para invertir una cadena (string).
    void reverse(char str[], int length)
    {
    int start = 0;
    int end = length -1;
    while (start < end)
    {
    swap(*(str+start), *(str+end));
    start++;
    end--;
    }
    }

    Segundo, implementar nuestra función itoa:

    // Función itoa()
    char* itoa(int num, char* str, int base)
    {
    int i = 0;
    bool isNegative = false;

    // Manejar 0 explícitamente, de lo contrario se imprima una cadena vacía para 0.
    if (num == 0)
    {
    str[i++] = '0';
    str[i] = '\0';
    return str;
    }

    // En el estándar itoa(), los números negativos se manejan solo con la base 10.
    // De lo contrario, los números se consideran sin signo.
    if (num < 0 && base == 10)
    {
    isNegative = true;
    num = -num;
    }

    // Procesar dígitos individuales.
    while (num != 0)
    {
    int rem = num % base;
    str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
    num = num/base;
    }

    // Si el número es negativo, agregar '-'.
    if (isNegative)
    str[i++] = '-';

    str[i] = '\0'; // Agregar fin de cadena.

    // Invertir la cadena.
    reverse(str, i);

    return str;
    }

    Un saludo.

    ResponderEliminar