Control de Colisiones

Este pequeño tutorial va dedicado a todos aquellos que están haciendo el curso de crea tu propio RPG. Según me van contando en los comentarios no llegan a entender bien como funciona el control de choque o colisión.




Lo primero he de decir, que todo hace referencia al tutorial "El primer Escenario", no se trata de nada nuevo, sino que se explicará como funciona.

Primero nos centramos en el movimiento del personaje.

void player::pinta()
{
    masked_blit(prota, buffer, animacion*32, direccion*32, x, y, 32,32);  
} 


Esta función player::pinta() que pertenece a la clase player y nos muestra como funciona el posicionamiento del personaje mediante las variables x,y.
Estas variables están limitadas en la función player::teclado(), que se encarga de que el personaje no salga del campo visual.

      // limites globales
      if ( x < 0 ) x = 0;
      if ( x > PANTALLA_ANCHO ) x = PANTALLA_ANCHO;
      if ( y < 0 ) y = 0;
      if ( y > PANTALLA_ALTO )  y = PANTALLA_ALTO;   

Según muestra el código anterior la variable "x" puede un tener un valor que oscila entre el 0 y el ancho de la pantalla, y la variable "y" puede tener un valor entre el 0 y el alto de la pantalla.

Todo esto es para decir que el personaje se mueve por la pantalla. 
Viendo esto ahora veo un posible fallo, y es debido a que cuando se pinta el personaje en la posición x,y, quiere decir que la imagen se empieza a situar a partir de la posición x,y, siendo esta posición la esquina superior izquierda de la imagen a mostrar.

Y según los limites si se sitúa "x" en el ancho de la pantalla y la "y" en el alto de la pantalla, solo estará visible el primer pixel, y el resto estará fuera de la pantalla y no se verá nada.

// actualiza el estado del juego
void actualiza_juego()
{
    int ax,ay;
    ax = jugador.getx();
    ay = jugador.gety(); 
    jugador.teclado(); 
    
    // comprobar si colisiona con el mapa
    bool choca = false;
    int px = jugador.getx()-160;
    int py = jugador.gety()-160+16;    
    for ( int ci=0; ci < 32; ci++)
    {
        for (int cj=0; cj < 16; cj++)
        {

            if ( getpixel( choque, px+ci, py+cj) == 0xff0000 ){
                 choca = true;
                 ci = 32;
                 cj = 16;
            }
            if ( getpixel( choque, px+ci, py+cj) == 0x00ff00 ) salir = true;
        }
    }    
    if ( choca ){
         // vuelve al estado anterior
         jugador.posiciona( ax,ay );
    }
        
}

La función actualiza_juego() se encarga de controlar la colisión del personaje con el mapa de choque. Al principio se guarda la posición actual del jugador en las variables ax,ay. Luego se calcula el valor de px,py que es la posición del personaje sobre el escenario, esto es necesario debido a que el mapa utilizado es pequeño y se ha centrado en pantalla y para ello se ha colocado en la posición 160,160.

Como el personaje es posicionado por la pantalla el punto (0,0) es la esquina superior izquierda, por ello se suma 160 a cada eje para que empiece en la posición (0,0) de la imagen de la casa, ya que esta está situada a esa distancia con respecto a la pantalla. Todo esto debe de cambiarse si el mapa es grande, es decir, que el tamaño del escenario es superior al tamaño de la pantalla.

Los dos bucles for son utilizados para recorrer toda la superficie que ocupa el personaje, que realmente debería ser de 32x32, pero se hace de 32x16. Por un lado de este modo es mas rápido pues se comprueba la mitad de puntos y por otro permite que el personaje se superponga sobre los objetos que colisiona.

La parte que esta pintada de verde es la que se comprueba que choque.

La primera condición controla si el pixel leído es de color rojo ( 0xff0000 ) en caso afirmativo la variable choca tiene valor true, y se ponen las variables a ci a 32 y cj a 16 para que los bucles de estas variables terminen en el siguiente ciclo.

La segunda condición controla el color de la salida de la casa, en este ejemplo el color de choque de la salida es verde ( 0x00ff00 ). 

Y finalmente la ultima condición comprueba si choca, en caso de que se cumpla quiere decir que ha habido colisión y por ello vuelve a una posición anterior.

Espero que con todo esto quede resuelto las dudas.

SHARE
    Blogger Comment

4 comentarios:

  1. Hola Koday !!!
    Está quedando mucho mejor que el viejo blog :D
    Te hago una consulta con respecto al viejo blog ya que estoy siguiendo ese que está terminado!
    El Allegro no me reproduce el sonido .... hice un copiar pegar de tu código y me compiló perfecto pero cuando ejecuto el juego me sigue saliendo sin sonido !!
    Alguna idea de porque puede ser ??
    Será que no me auto-detecta la placa de sonido o algo así ??
    Un abrazoooo

    ResponderEliminar
    Respuestas
    1. ummm ... pueden ser muchas cosas. Que formato de audio estas intentado reproducir? Será mejor que pongas tu duda en la sección que copiaste y estas probando, para así saber que comandos estas utilizando y poder comentarte los posibles fallos o problemas que te pueden surgir.

      Eliminar
  2. cuando tu mapa cubre el ancho y alto de la pantalla que medidas le pones? en px y py? no logro hacer que funcione la colision

    ResponderEliminar
    Respuestas
    1. Si tu mapa tiene el mismo tamaño que la pantalla debes de quitar el -160 cuando se calculan px,py dentro de la función actualiza_juego(). Para mas información haz CLICK aqui!!.

      Eliminar