viernes, 29 de junio de 2012

Juego de la serpiente

Aqui traigo mi codigo de un juego muy conocido, el juego de la serpierte.

Una imagen vale mas que mil palabras, pero esta imagen no muestra casi nada U_U
... ya que el juego es asi de simple.
La linea verde es la serpiente y el cuadrado morado es lo que debe comer.

Para ello creé una clase llamada gusano, y dentro de ella utilizo una estructura llamada coord que contiene dos variables x, y. Se utilizan para el cuerpo, que esta definido como una matriz de 100, por tanto, nuestro gusano podrá tener un tamaño máximo de 100.
tam: indica el tamaño actual del gusano.
dir: indica la dirección en la que esta caminando 1: arriba 2: abajo  3: izquierda  4:derecha


struct coord{
    int x,y;   
} comida;

class gusano{
      int tam;
      bool bloquea( int _x, int _y);
   public:
      int dir;    
      coord cuerpo[100];
      gusano();
      bool choca();       
      void pinta();
      void teclas();
      void mueve();
      bool come();
      int tami();
      bool bloqueado();
};



 // Inicializa al gusano
gusano::gusano(){
   tam = 3;
   dir=1;
   int x = ANCHO/40;
   int y = ALTO/40;   
   for ( int c = 0; c < tam; c++){
       cuerpo[c].x = x;
       cuerpo[c].y = y+c;
   }           
};

// funcion para obtener el tamaño del gusano
int gusano::tami(){
    return tam;
};
 
// comprueba si el gusano choca con el mismo
bool gusano::choca(){ 
    int posx, posy;
    posx = cuerpo[0].x;
    posy = cuerpo[0].y;
    if ( dir == 1) posy = cuerpo[0].y-1;
    if ( dir == 2) posy = cuerpo[0].y+1;
    if ( dir == 3) posx = cuerpo[0].x-1;
    if ( dir == 4) posx = cuerpo[0].x+1;

    if ( posx < 0 ) return true;    
    if ( posy < 0 ) return true;
    if ( posx > (ANCHO/20)-1 ) return true;
    if ( posy > (ALTO/20)-1 ) return true;    
    
    for ( int c = 0; c < tam; c++){
        if (posx == cuerpo[c].x && +
            posy == cuerpo[c].y ) return true;        
    };     
    return false;
};
 
// pinta el gusano por pantalla
void gusano::pinta(){
   int x,y;
   for ( int c = tam-1; c >= 0; c--){
       x = 20 * cuerpo[c].x;
       y = 20 * cuerpo[c].y;
       if ( c == 0 ){
           rectfill(buffer, x, y, x+20, y+20, 0x00FF00);         
       }else{     
           rectfill(buffer, x, y, x+20, y+20, 0x00AA00);
       }
   }
};

// controla las teclas para mover al gusano, dando un valor a dir, segun la direccion que se ha pulsado.
void gusano::teclas(){
     if ( key[KEY_UP] ){
          dir = 1;
     }
     if ( key[KEY_DOWN] ){
          dir = 2;
     }
     if ( key[KEY_LEFT] ){
          dir = 3;
     }
     if ( key[KEY_RIGHT] ){
          dir = 4;
     }               
};
// mueve al gusano, la ultima parte toma el valor de su parte anterior, y asi hasta llegar 
// a la cabeza  y la cabeza toma un nuevo valor segun la direccion.
void gusano::mueve(){
   if ( !choca() ){
     
     for ( int c = tam-1; c > 0 ; c--){
         cuerpo[c].x = cuerpo[c-1].x;
         cuerpo[c].y = cuerpo[c-1].y;              
     }
     if ( dir == 1 ){

          cuerpo[0].y -= 1; 
     }
     if ( dir == 2 ){

          cuerpo[0].y += 1; 
     }
     if ( dir == 3 ){

          cuerpo[0].x -= 1; 
     }
     if ( dir == 4 ){

          cuerpo[0].x += 1; 
     }
     // colocamos los limites
     if ( cuerpo[0].x < 0 ) cuerpo[0].x=0;
     if ( cuerpo[0].x > (ANCHO/20)-1 ) cuerpo[0].x=(ANCHO/20)-1;
     if ( cuerpo[0].y < 0 ) cuerpo[0].y=0;
     if ( cuerpo[0].y > (ALTO/20)-1 ) cuerpo[0].y=(ALTO/20)-1;       
     
   }
};

// se encarga de comprobar si ha llegado a la comida, y aumenta su tamaño
bool gusano::come(){
     if  ( comida.x == cuerpo[0].x && 
           comida.y == cuerpo[0].y ){
          tam++;
          return true;          
     }
     return false;
}
 
// comprueba si en la posicion _x,_y existe una parte del gusano
bool gusano::bloquea(int _x, int _y){
     for ( int c = tam-1; c > 0 ; c--){
         if ( cuerpo[c].x == _x && cuerpo[c].y == _y ) return true;         
     }
     return false;
};

// comprueba si el gusano esta bloqueado
bool gusano::bloqueado(){
     int x = cuerpo[0].x;
     int y = cuerpo[0].y;
     return bloquea(x+1,y) &&
            bloquea(x,y+1) &&
            bloquea(x-1,y) &&
            bloquea(x,y-1);
};


Y a continuación el programa principal.

int main() 
{    
    allegro_init();
    install_keyboard();
    
    set_color_depth(32);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, ANCHO, ALTO, 0, 0);
    
    srand (time(NULL));
    
    puntos = 0;
    gusano serpiente;
    
    buffer = create_bitmap(ANCHO, ALTO);
    
    comida.x = rand()%(ANCHO/20);
    comida.y = rand()%(ALTO/20);
    while ( !key[KEY_ESC] )
    {
        clear_to_color(buffer, 0x000000);  
        serpiente.teclas();
        serpiente.mueve();

        rectfill(buffer, comida.x*20, comida.y*20, (comida.x*20)+20, (comida.y*20)+20, 0x6633DD);
        serpiente.pinta();
        if ( serpiente.come() ){
                comida.x = rand()%(ANCHO/20);
             comida.y = rand()%(ALTO/20);
             puntos+=5;
        }
        char c1[10];
        textout_ex(buffer, font, "Tamano:", 25, ALTO-35,  0xfff000, -1);
        textout_ex(buffer, font, itoa(serpiente.tami(),c1,10), 90, ALTO-35,  0xfff000, -1);        
        textout_ex(buffer, font, "Puntos:", 25, ALTO-25,  0xfff000, -1);
        textout_ex(buffer, font, itoa(puntos,c1,10), 90, ALTO-25,  0xfff000, -1);
        
        if ( serpiente.bloqueado() ) textout_ex(buffer, font, "bloqueado", 25, ALTO-45,  0xfff000, -1);
        
        blit(buffer, screen, 0, 0, 0, 0, ANCHO, ALTO);
        rest(50);
    }
    
    
    destroy_bitmap(buffer);
    
    return 0;
}
END_OF_MAIN();

El juego esta hecho de manera de que no tiene fin pues no te matan, solo controla los choques para que no te pises. Por tanto se puede dar el caso de quedarte bloqueado rodeado por tu propio cuerpo. Para salir del juego debes pulsar ESC.
En el comienzo de nuestro programa debemos añadir las siguientes lineas, para declarar las variables globales que se utilizan en el programa, se utiliza el comando #define para las constantes.

#include <allegro.h>

#define ALTO  480
#define ANCHO 640

int puntos;

BITMAP *buffer;


Si todo se ha copiado correctamente, tendremos el juego listo para compilar y jugar. A continuación os dejo un video del juego.

Menudo viciao el que juega XD jajajaja

Si quieres el codigo completo puedes hacer clic aqui para descargar en un archivo RAR
Si quieres jugar directamente puedes hacer clic aqui para descargar el ejecutable en RAR



Si deseas jugar, visita el este link

13 comentarios:

  1. Hola, oye probé este ejemplo en code::Blocks pero no tengo resultados mas que muchos errores no se si me podrias pasar el codigo por favor D:

    ResponderEliminar
    Respuestas
    1. Hola, si necesitas ayuda plantea tus dudas y los errores en el foro http://creatusjuegosdecero.webege.com

      Eliminar
  2. hola que tal, oye una pregunta todo eso va dentro del dev C++ en un solo archivo fuente o son varios dentro del mismo proyecto???

    ResponderEliminar
    Respuestas
    1. Va todo dentro de un unico archivo, el orden en el que debes copiar los bloques de codigo son: Primero el tercero, despues el primero, y por ultimo el segundo.

      Eliminar
  3. yo kiero ese amigo pero en ensamblador, lo tendras porahi?? estoy programando en RADAMS

    ResponderEliminar
  4. hola camarada, disculpa, podrías decirme como hacerlo que valla un poco mas lento? muchas gracias de antemano.

    ResponderEliminar
    Respuestas
    1. Tienes que cambiar el valor que aparece en el comando rest, el que esta despues de pintar por pantalla. En el ejemplo esta rest(50), lo cual hace una pequeña pausa de 50 milisegundos. Si aumentas este valor la pausa será mayor y por consiguiente será el juego mas lento.

      Eliminar
  5. Cambie que para cuando el gusano toque los limites se termine el juego, el problema es cuando la comida sale muy a ras del limite, no alcanza a comersela y por lo tanto el juego acaba, es decir toca el limite antes de poder comer la comida.

    ResponderEliminar
  6. hola, tengo una duda, supongamos que no quiero limites,
    me explico, quisiera que cuando llegue al limite de arriba salga por el limite de abajo y viceversa, de igual forma por los lados derecho e izquierdos, como tendria que validarlos?

    ResponderEliminar
    Respuestas
    1. hola, tendrás que modificar la función choca, lineas del 52-55 estas controlan el choque con los bordes, debes quitarlo, y luego cambiar en la funcion mueve(), las lineas 121-124 cambiar por ejemplo
      if ( cuerpo[0].x < 0 ) cuerpo[0].x=(ANCHO/20)-1;
      if ( cuerpo[0].x > (ANCHO/20)-1 ) cuerpo[0].x=0;

      Eliminar
    2. como me puedo comunicar con usted, quisiera que me ayudara con eso de los limites. gracias!

      Eliminar
    3. Si tienes alguna duda puedes plantearla en el foro http://creatusjuegosdecero.webege.com/index.php o si quieres escribe a mi correo kodaygames@gmail.com

      Eliminar
  7. hola, gracias por tu codigo, me gustaría agregarle música como podría hacerlo?

    ResponderEliminar

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...