Tema: Colisiones.
Ver Mensaje Individual
  #1 (permalink)  
Antiguo 24/05/2016, 17:38
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Colisiones.

Hasta ahora, para que mis programas vieran si hay colisión o no, usaba una función de Flash que considera rectangulares a cualquier objeto. No es muy preciso cuando el objeto no es realmente un rectángulo, y menos entre más grande sea. No lo recomiendo porque tarda en ocurrir, pero pueden verlo en este jueguillo que hice hace algunos meses:
https://dl.dropboxusercontent.com/u/169164922/992.swf
Dedíquense a evadir los triángulos, especialmente los que sean más anchos que tu circulo, pues en ese caso si hay colisión el juego se detiene lo cual es game over. Llega un punto en que los triángulos son muy grandes y aunque no haya colisión el programa interpreta que sí. Por la falta de precisión que dije.

Bueno, intentando mejorar ese jueguillo en el aspecto de las colisiones, empecé a intentar ver cómo sería el método si no usara el que venía usando. Pero no iba a empezar por circulo-triángulo, sino por lo que me pareció más sencillo que es punto-punto.

Si P1x == P2x && P1y == P2y
// hay colisión

Siguiente caso: Punto-segmento.
En el siguiente "tester" le llamé recta al segmento porque no sabía que hubiera una diferencia importante (y ahora me pregunto si basta con decir segmento o debería decir "segmento de recta"), pero la cosa es que funciona bastante bien.
https://dl.dropboxusercontent.com/u/...y%20recta3.swf

El método que uso es:
Si el punto está en una zona pintada (no blanco)

entonces no hay colisión.

Sino... Imaginen que trazan una línea vertical que pasa por el punto. También pasará por el segmento. El punto x del segmento, por el que pasa la línea vertical, es el mismo x del punto suelto. Bueno, lo que hago es calcular cual es el punto y correspondiente al punto x, del segmento, y si dicho y es igual al y del punto suelto entonces hay colisión, sino no.

Código:
if (Recta._x<=Punto._x && RectaXfin>=Punto._x) {
    if (Recta._y<=Punto._y && RectaYfin>=Punto._y) {
        Porce = (Punto._x-Recta._x)*100/(RectaXfin-Recta._x);
        RectaYCorresondiente = (RectaYfin-Recta._y)*Porce/100+Recta._y;
        if (RectaYCorresondiente == Punto._y) {
            Colision = true;
        }
    }
}
Por lo que vi, eso más bien se hace con un método relacionado con "la pendiente", yo lo hice como pude porque nunca en mi vida usé "la pendiente" (o quizá inconscientemente, puede ser, "vectores y la norma", pero tampoco es algo de lo que entienda mucho), en cambio porcentajes sí.

Bueno... el siguiente paso que intento dar es segmento-segmento, pero me interesan todos los casos. O sea, 1ero quisiera el segmento-segmento, y mientras los mods me dejen seguimos.

Había leído esto por arribita:
http://www.genbetadev.com/programaci...ceptos-basicos
Y esto (me pareció muy complicado):
http://es.slideshare.net/IvanDragoge...as-y-segmentos

Voy a leer mejor el 1er link, pero antes decir lo que más o menos tengo pensado, aunque no confío mucho en que funcione y lo veo poco eficiente.
Si el 2ndo segmento no toca la zona blanca, no hay colisión.

Eso se chequea con los x y también con los y (imaginen que la imagen se rotara). Si bien ahí hay 3 segmentos, está mostrando 2 casos en que sólo se comparan 2 cada uno; un caso en que se chequea el segmento central y el izquierdo y otro en que se chequea el central con el derecho.
La fórmula más especificamente sería:
Si s1x1 <= s2x2 && s1x2 => s2x1
___Si s1y1 <= s2y2 && s1y2 => s2y1
______// puede haber colisión
Esto no lo comprobé así que tómenlo con pinzas, pero sería algo similar.

Lo poco eficiente es el 2ndo paso. Consiste en ir eliminando las partes que están "más allá". Así:


No tengo claro si cada vez que se elimina algo habría que volver a usar el método de arriba, pero la cosa es que, si hay colisión, por más que se eliminen partes va a decir "puede haber colisión", bien, pero nunca se llega a saber si la hay o no, y serían muchos chequeos.

¿Ideas?

Por otro lado, tendría que leer mejor esto:
http://blog.gskinner.com/archives/20...8_shape_b.html
Pero básicamente no lo entendí.

Esto se dice que es un método similar:
Cita:
La forma más precisa y más rápida (a nivel de pixel) sería:
En una función o clase:
Asociar a cada MC u objeto un rectangle de sus dimensiones.
Usar rectangle.intersection para determinar si hay un rectángulo común que es lo que devuelve.
si = 0 (empty) salimos fuera
Si hay rectangulo: copiar esa zona ( tomando los datos del rectángulo respuesta de ambos mc con un draw de ese rectángulo en un bitmap que creamos temporal mediante dos threshold de transparencia y add en el segundo draw.
los 2 threshold darán un resultado numérico cada uno que se suma.
Al temporal un threshold nuevo también de zona transparente. Su valor se compara con la suma anterior.
Si son distintos: hay colisión.
Si son iguales.....todavía no hay colisión pero puede faltar poco. Recordemos que el rectángulo no es vacio.
De aquí podríamos tomar sus bounds y si el movimiento esta en ese vector (esquina de uno menos esquina del otro) ...pronto chocarán ( útil para movimientos de IA)
Como el rectángulo será siempre muy pequeño ( o empty) lo ejecutará muy rápido.
Si el objeto está girado o escalado no importa, el draw se hace con el objeto transformado.
Uffffff......Creo que hubiera tardado menos en hacerlo que en explicarlo.
Idem.

Bueno, voy a leer mejor antes de volver, y especifico mejor qué cosas no entiendo, pero ya pueden ir respondiendo. Me sirve algo así "específico" de Flash pero también tengo interés en métodos más rebuscados, que no requieran mucho conocimiento de matemática. Gracias.