Introducción a la programación de Juegos para Pc.

 

La diferencia fundamental entre programar un juego y programar cualquier otra aplicación consiste en la manera de encarar la lógica (las decisiones que debe tomar la computadora) del juego, la cual difiere si se trata de un juego estilo pac-man, al estilo del mario (plataformas), Carreras de autos, Space Invaders, Estilo Doom o Aventuras Gráficas.

 

Veremos cada uno por separado, primero en modo texto ( yo sé que no es el ideal y los gráficos no son nada atractivos) que nos permitirá concentrarnos en la lógica para luego cuando sepamos lo que queremos, poder agregar gráficos y sonidos sin necesidad de cambiar gran parte del código .

 

Forma que utilizaremos para programar los juegos:

 

La máquina debe tomar decisiones lógicas , estas decisiones se basan en eventos . Como estamos programando en una plataforma (DOS) que no está orientada a eventos debemos guardar la información de que dichos eventos se produjeron  en variables (banderas o flags) , para utlizarla cuando sea necesario. Quiero decir con esto que si yo pulso la barra de espacio para disparar un misil , en la subrutina de teclado , voy a encender una bandera "bDisparo" indicando que el jugador disparó un misil . En la subrutina de disparo controlaré la bandera de disparo para saber si debo dibujar o no el misil en pantalla .

 

Otro elemento de programación que utilizaremos son las estructuras . Una estructura es un conjunto de datos , que pueden ser de diferente tipo, agrupados bajo un nombre único . Podemos compararlo con una base de datos donde una tabla agenda contiene los campos nombre, dirección , teléfono. Una estructura similar nos quedaría :

 

         estructura {

                             char nombre[ 20 ];

                             char direccion [20] ;

                             int telefono ;

                             } agenda ;

 

Para trabajar con los campos de la estructura utilizamos la forma :

 

               agenda.nombre

 

Si queremos tener varias personas en nuestra agenda debemos convertir nuestra estructura a un array o vector de estructuras.

 

         estructura {

                             char nombre[ 20 ];

                             char direccion [20] ;

                             int telefono ;

                            } agenda [ 100] ;

 

Para acceder al primer nombre de este array de la estructura agenda escribimos :

 

                agenda[ 1 ].nombre

 

En la programación de juegos utilizamos las estructuras para dos funciones principales : definir las propiedades de los objetos ( nave del jugador , misiles, naves enemigas , personaje principal ) y definir el mundo o entorno por el cual se mueven nuestros personajes ( por ejemplo en un packman indico la ubicación de las paredes , las comidas, los fantasmas, la posición del jugador ).

 

 

Space Invaders :

 

Debemos comprobar que la nave/s invasora/s esté/n dentro de los límites de la pantalla , caso contrario, debemos tomar las decisiones pertinentes.

 

definir IZQUIERDA -1

            DERECHA 1

 

     nave.x = nave.x + nave.dirección         // muevo la nave sumando o restando 1

     si (nave.x > ANCHO_PANTALLA)

            nave.dirección = IZQUIERDA;

     si (nave.x < 1)

            nave.dirección = DERECHA;

 

 

Nota : las palabras en mayúscula son constantes. Lo que hace este código es mover la nave en la dirección dada por nave.dirección . Sumando o restando los valores contenidos en DERECHA e IZQUIERDA respectivamente. Haciendo rebotar la nave al llegar a los bordes.

 

Asimismo verificamos la posición del jugador y los comados ingresados por teclado :

 

            Jugador.x= Jugador.x + Jugador.direccion

             Si ( Jugador.x > ANCHO_PANTALLA)

                        Jugador.x = 1;

            Si (Jugador.x < 1)

                         Jugador.x= ANCHO_PANTALLA;

 

//////////////////////       fin rutina de movimiento

 

            tecla= TeclaPulsada();

            Si ( tecla = TECLA_DERECHA)

                        Jugador. direccion = DERECHA ;

            Si ( tecla = TECLA_IZQUIERDA)

                        Jugador. direccion = IZQUIERDA ;

            Si ( tecla= TECLA_ESPACIO)

                        bDisparo = SI ;

 

nota: Podemos ver una diferencia entre este código y el anterior en la forma de mover la nave del jugador , en vez de rebotar , aparece en el extremo opuesto de la pantalla . En este caso, la dirección del jugador no es establecida por programa sino que la establece el usuario al pulsar la tecla correspondiente . También comprobamos si el jugador desea disparar y encendemos la bandera bDisparo.

 

Lógica para detección de colisiones

 

Tenemos que indicarle al programa cuándo el misil choca contra la nave invasora para que :

-  Sume los puntos por nave destruida,

-  Deje de dibujar y mover la nave destruida ,

-  Comience a dibujar la explosión ,

-  Dibuje una nueva nave invasora en otra posición de pantalla

 

 

            Definir VALOR_NAVE  5

            Definir SI  1

            Definir NO 0

            Definir QUIETO 0    

 

            Si ( misil.x > nave.x   &&   misil .x < nave.x + nave. ancho  _

                    &&  misil. y > nave.y   &&   misil .y < nave.y+nave.alto)

                        Puntaje=Puntaje + VALOR_NAVE

                        bExplota =SI ;

                        nave. direccion = QUIETO ;    // dejamos de mover la nave

                        nave.x= 1;

                        nave.y=1;

 

           

 

                       

Mario  Bros

 

La principal diferencia que encontramos al programar un juego de "plataformas" es que debemos verificar permanentemente que nuestro jugador esté pisando o no el suelo (plataforma) y reaccionar  en consecuencia. Esto es:

 

          Si ( vPantalla(Jugador.x,Jugador.y +1) == " " )

                Jugador.y ++ ;                             //   Si no hay piso, se cae

 

       Si ( vPantalla(Jugador.x,Jugador.y +1) == "P " )

              Jugador.x+=DIRECCION ;               // Si hay piso continúa avanzando

    

       Si ( vPantalla(Jugador.x+DIRECCION,Jugador.y ) == "m" )

             Vidas--;                                 // Si se encuentra con un monstruo pierde una vida

              fSonido(1);                             // Llamo a la función de sonido

 

       Si ( vPantalla(Jugador.x+DIRECCION,Jugador.y ) == "t" )

             Puntaje+= 10;                       // Si encuentra un premio aumenta el puntaje

              fSonido(2);

 

 

Necesitamos una matriz que represente nuestra pantalla :

 

vPantalla[80][4] =

{"

                          t   t    t

                      PPPPPPPP           PPPPP                                              PPPPP

                  m                                                   t

  PPPPPPPPPPPPPPPPPPPPPPP          PPPPPPPPPPPPP          PPPPPPPPPPPPPPP"}

 

 

 

Need for Speed

 

Así como en los juegos de plataformas es necesario verificar permanentemente que en y-1 se encuentre el piso ( plataforma ), en los juegos de carreras se debe verificar que el jugador no toque los bordes de la pista , la cual estará contenida en una matriz ,ya que debido a que nosotros dibujamos la pista de carreras renglón por renglón, para dar sensación de movimiento, dicho renglón debe ser movido o copiado a través de la matriz hasta llegar al final de la misma y desaparecer. Por ejemplo:

 

            distancia = rand ( ) % 3                                 // previamente usaremos un randomize para

            for ( y =9; y >0 ; y--)                                     // iniciar el rand ( )

               for ( x =0 ; x < 10 ; x++)

                     pista [y][x] = pista [y-1][x];                   // bajo todos un renglón

   

            for (x=0; x< 10; x++)                                     // borro el primer renglón

               pista [0][x]= '  ' ;

 

             pista [0][distancia]= ' | ' ;                        // asigno los bordes de la pista a la matriz

            pista [0][distancia +7] = ' | ' ;

 

            for ( y=0 ; y<10 ; y++)                        // dibujo la matriz en pantalla

                 for (x =0 ; x< 10 ; x++ )

                {

                        gotoxy ( x+40 , y+5);

                        printf ( "%c", pista[y][x]);

               }

 

            gotoxy ( jugadorX,JugadorY) ;                  // dibujo el auto

            printf ( " A ");

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

            if ( pista [5] [jugador x-40] == ' | ' )              // subrutina de detección de colisiones

            {

                sound ( 450) ;

                delay (50) ;

                nosound ( );

            }