¿Como puedo mejorar esta colisión? JS "canvas"

Iniciado por SrTrp, 19 Agosto 2017, 04:26 AM

0 Miembros y 1 Visitante están viendo este tema.

SrTrp

Que creen que pueda mejorar esta función de colision de enemigos y jugador?  quisiera  saber como puedo hacer que no trasparece el enemigo si detecta cuando se topan.
Código (javascript) [Seleccionar]

//AQUI ESTA CUANDO HAGO LA COLISION ENTRE ENEMIGO Y JUGADOR
if(player.intersects(enemigos[i])&&player.timer<1){
                    player.vida--;
                    player.timer=20;
             
                }


//AQUI ESTA LA FUNCION DE COLISION
Rectangle.prototype.intersects=function(rect){
        if(rect!=null){
            return(this.x<rect.x+rect.width&&
                this.x+this.width>rect.x&&
                this.y<rect.y+rect.height&&
                this.y+this.height>rect.y);
        }
    }

0xFer

Cita de: SrTrp en 19 Agosto 2017, 04:26 AM
 quisiera  saber como puedo hacer que no trasparece el enemigo si detecta cuando se topan.

Código (javascript) [Seleccionar]

if(player.intersects(enemigos[i])&&player.timer<1){
                   player.vida--;
                   player.timer=20;

               }
else{
 
}


En caso de que se topen solo baja la vida, en caso contrario sigue con las acciones normales de desplazamiento.
Código (java) [Seleccionar]
int getRandomNumber(){
    return 4; //chosen by fair dice roll
              //guaranteed to be random
}

engel lex

#2
creo que la intersección está mala... solo intersectará si está completamente adentro...

es preferible que definas unas clases decentemente
Código (javascript) [Seleccionar]
class Rect{
 constructor(x,y,w,h){
   this.x = x;
   this.y = y;
   this.w = w; //ancho
   this.h = h; //alto
   this.l = x; //left
   this.r = x+w; //right
   this.t = y; //top
   this.b = y+h; //bottom
 }

 colision(otro){
   //si this l está entre l y r de otro hay colisión izquierda
   //si this r está entre l y r de otro hay colisión derecha
   //si this l es mayor que otro l y this r es menor que otro r, otro adentro de this
   //si this l es menor que otro l y this r es mayor que otro r, this adentro de otro
   //repetir con vertical
 }
}

var cajaDeColision  = new Rect (10, 10, 50, 50);

if(cajaDeColision.colision(otraCajaDeColision)){
 console.log("hay colision");
}




El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Serapis

#3
No hay mucho de donde mejorarla. Técnicamente es correcta. Aunque es cierto que algo si se puede.

Te comento. Tu estás considerando siempre dos áreas, pero vamos a hacernos una imagen mental, para que sea más fácil entender donde quiero ir a parar.

imagina que tienes una espda y luchas contra otro que también tiene una espada. El área de cada uno, entonces es uno mismo y las dimensiones de la propia espada. es fácil de entender, verdad?

Bien, entonces la cuestión es... a quién le importa, tu espalda o 'su' espalda?. quiero decir, que la intercepción se basará en un punto, y no es preciso un área.

Supongamos que 'el jugador' es This (tu, yo, el que lo lea que se ponga en primera persona) y que el 'enemigo' es el área (rect).... con esto y lo dicho previamente pasemos al pseudocódigo...

Clase cThis
     entero X, Y, Width, Height
     entero Right, Bottom

     // Asignación de todos los datos del área (se reposiciona y redimensiona)
     Funcion MoverYDimensionar(rect Area) // puedes pasar valores individuales, (x,y,Width,Height) o incluso solo dos puntos de la diagonal principal '\' y calcular como proceda, o bien sobrecargar la función si se usan más que solo una.
         This.x = Area.X
         This.y = Area.Y
         This.Width = Area.Width
         This.Height = Area.Height

         This.Right = (This.X + This.Width)
         This.Bottom = (This.Y + This.Height)
     Fin Funcion

     // Cuando se desplaza (pero mantiene el tamaño):
     //       ('Inc'remento indica si los valores son relativos o absolutos)
     Funcion Mover(entero X, entero Y, buleano Inc)
         Si (Inc = FALSE)
             This.X = X
             This.Y = Y
         Sino
             This.X += X
             This.Y += Y
         Fin si

         This.Right = (This.X + This.Width)
         This.Bottom = (This.Y + This.Height)
     Fin funcion
   
     // Cuando se cambia de tamaño (pero mantiene su posición):
     //       ('Inc'remento indica si los valores son relativos o absolutos)
     Funcion Dimensionar(entero Witdth, entero Height, buleano Inc)
         Si (Inc = FALSE)
             This.Width = Width
             This.Height = Height
         Sino
             This.Width += Width
             This.Height += Height
         Fin si

         This.Right = (This.X + This.Width)
         This.Bottom = (This.Y + This.Height)
     Fin Funcion

// y por fin la detección de la colisión.
     // El detector de colisión, ahora exige menos matemáticas.
     Buleano = Funcion ColisionaCon(cThis cT)
          // si de entrada se aleja horizontalmente, no perdemos tiempo en comprobaciones verticales
         Si ( cT.Rigth > This.X) y (cT.X < This.Right) luego              
             Devolver ( cT.Bottom > This.Y) y (cT.Y < This.Bottom)
         Sino
             Devolver FALSE
         Fin si
     Fin Funcion
Fin clase



Tanto 'nosotros' (player) como el 'enemigo' seríamos instancias de cThis, y se llamaría así:
Si Player.ColisionaCon(Enemigo) luego
    ...


Funciona y es más rápido, porque:
A - Se calcula una única vez, el valor 'Right y Botton', y se guardan, en lo sucesivo ya no se calculan. Por tanto cada vez que haya que hacer la detección de colisión, nos ahorramos 4 sumas.
B - También contribuye a la velocidad que la comparación la dividimos en dos pasos, primero horizontal y luego vertical, (no importa si fuera al revés, de hecho si fuere más frecuente los movimientos verticales, sería mejor poner delante la comprobación vertical). al dividirlo en dos pasos no forzamos una posterior comprobación si la previa ya falló, pero incluso si es necesario la segunda comprobación también es ligera (no realiza sumas).

En Resumen, la detección ahora solo requiere:
   2 ó 4 comparaciones y 0 sumas
Antes requería:
   4 comparaciones y 4 sumas


Las sumas se hacen una sola vez cuando se establece/modifica el tamaño o se reposiciona, pero no con cada verificación de colisión.
Aunque al final viene a ser lo mismo, sin embargo el momento es diferente, al mover o redimensionar, no suele haber tanta carga de trabajo, luego... deja más tiempo para actualizar valores, en cambio cuando se exige detectar suele haber más trabajo 'pesado' en curso, entonces aligerar de ahí es adecuado.
En resumen, desplazamos la carga de trabajao a momentos menos activos, aligerando los momentos más activos. Aunque siempre va a depender de cada caso concreto...

...pero bueno, lo que pedías es posible...


---------------------
p.d.: Al publicar ya había más respuestas... te comento: asegúrate tras rehacer tu código que funciona en todos los casos... he aquí una imagen de los casos posibles (considera el cuadro rosado como el jugador y los azules como el enemigo), falta el caso de que el jugador esté completamente dentro del área del enemigo (el cuadro rosa dentro de uno azul), en las imágenes quedaba sobrecargado y se prestaba a confusión así que la he evitado.