Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Obtener Cara De Colision

Iniciado por Sacrifai, 05 de Enero de 2005, 12:19:23 PM

« anterior - próximo »

Sacrifai

 Pues sigo con algunas dudas sobre colisiones. Esta vez se trata de devolver la cara con la que ha colisionado a partir de esta formula:


int Colision(SDL_Rect origen, SDL_Rect destino)
{
int centro_x1 = origen.x + (origen.w >> 1);
int centro_y1 = origen.y + (origen.h  >> 1);
 
int centro_x2 = destino.x + (destino.w >> 1);
int centro_y2 = destino.y + (destino.h  >> 1);

int delta_x =  centro_x1 - centro_x2;
int delta_y =  centro_y1 - centro_y2;

int sum_x = (origen.w/2) + (destino.w/2);
int sum_y = (origen.h/2) + (destino.h/2);

if( abs(delta_x) <= sum_x && abs(delta_y) <= sum_y )
 return 1;
else
 return 0;
}


A los deltas les aplico el valor absoluto solo cuando los compruebo, asi los tengo intacto para hayar el lado... pero no se como abordarlo  (nooo) .

Gracias.

Lord Trancos 2

 Uffff... q codigo mas enrevesaooo para comprobar una colision de caja vs caja.   :P
Ademas primero usas desplazamientos para dividir y despues no los usas.  :huh:

Tal y como te dije, yo uso este codigo:


function RectCollision(var _r1, _r2: TRect): boolean;

begin
Result := not ((_r1.Right  < _r2.Left) or (_r1.Bottom < _r2.Top) or
               (_r2.Right  < _r1.Left) or (_r2.Bottom < _r1.Top));
end;


Es bastante mas sencillo, y debe de funcionar pq es el que use en mi matamarcianos.  ;)

De todos modos, si quieres usar tu metodo; puedes ahorrarte algunos calculos si en lugar de usar SDL_Rect, usas tu propia estructura y te guardas las mitades de tamaño de los rectangulos.

Respecto a averiguar con que cara a colisionado.... esta joio, puesto que para eso necesitas saber como se mueven las cajas. Y en la formula que pones o la que pongo yo solo puedes saber si hay colision; pero no cuando se produce y donde.

Ademas, ten en cuenta que si las cajas se mueven muy rapido; puede darse la situacion de que una quede dentro de otra de un frame para otro. La solucion mas sencilla suele ser dividir el tiempo en pequeños espacios ("time steps") donde no se pueda producir esta situacion; es decir, q por muy rapido que vaya la pelota (o lo que sea), nunca pueda terminar dentro de una caja de un frame para otro (y no digamos ya atravesar un objeto....); sino que siempre haya un "time step" en el que la pelota toque algun lado del rectangulo.

Si es una colision pelota vs caja; con el metodo que te dije del otro post, puedes saber que lados colisionan; y el primer lado deberia de ser cuyo punto de colision se encuentre a menor distancia del centro de la esfera.

on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Lord Trancos 2

 La otra solucion seria; considerar el movimiento. Para ello lo que se suele hacer es considerar uno de los objetos como inmovil para simplificar el problema. Por ejemplo; imaginate que quieres saber el tipico problema para determinar cuando un tren A que va a 100km alcanza a otro tren B que va a 80km; seria lo mismo si el tren B esta fijo y el tren A va a 20km. Aun asi, los calculos suelen ser mucho mas complejos que usando "time steps".... (nooo)
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Sacrifai

 Gracias por las respuestas, tendré que usar colision pelota contra caja. De todas formas algun metodo ha de haber aunque no se use esa formula ¿ no?  

Lord Trancos 2

Cita de: "Sacrifai"Gracias por las respuestas, tendré que usar colision pelota contra caja. De todas formas algun metodo ha de haber aunque no se use esa formula ¿ no?
Si vas a comprobar colisiones contra todos los ladrillos; antes de hacer comprobacion caja vs pelota, haz una caja vs caja; asi podras descartar muchos calculos.

Compruebas caja vs caja contra todos los ladrillos y despues aquellos ladrillos con los que haya habido colision haces una comprobacion caja vs esfera para confirmar dicha colision.

Respecto a lo de algun metodo habra....  pues claro.... lo que pasa es que primero tienes que decidir que modelo vas a seguir para las colisiones:
A - Usar "time steps"
B - Considerar el movimiento

Y despues es cuestion de buscar los algoritmos mas chachis para el metodo que eligas.

Aqui tienes unos cuantos algoritmos:
http://www.magic-software.com/IntersectionBody.html

on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Lord Trancos 2

 Por cierto en www.sourceforge.net hay algunos clones de arkanoid, puedes echarles un vistazo para ver como han resuelto las colisiones.
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

TheAzazel

 uhmmm, Sacrifai que es lo q kieres hacer? pq para hacer un "arkanoid" y tal.. hay metodos mucho mas sencillos. Hoy en dia da un poco igual ya que con las CPU que hay....uno tiene q ser muy bestia para colapsarla con estos calculos pero..si quieres que vaya optimo y funcione en cpu antiguas... primero, para que lo quieres hacer? y luego ya se utiliza el metodo mas optimo :)
en un ping-pong q hice por ahi..compruebo las colisiones en un par de if  :P , me podia haber puesto a colision caja-circulo pero...para q? no es necesario en ese caso jeje

senior wapo

 Lo suyo es tener en cuenta la direccion del movimiento o el origen del movimiento, pero si quieres un truco guarro que "aparentemente" funciona bien (de cara al jugador, no matemáticamente):

Resta al centro de la caja el centro el centro de la pelota, eso te da un vector 2D. Clasifica ese vector como mirando para arriba, para abajo o hacia un lado (miras si su componente horizontal es mayor que la vertical, y para que lado). Son 4 posibilidades, cada una corresponde a un lado de la caja con la que dices haber colisionado.

Si el vector te sale mirando hacia abajo has colisionado con el lado superior, si te sale mirando a la derecha has colisionado con el lado izquierdo, etc... (siempre el lado de la posición contraria).

Guarrillo, pero rápido y funciona.
Este truco simplemente divide el espacio alrededor de la caja en 4 cuadrantes alineados con las DIAGONALES de la caja (no con los ejes). Si la caja no es cuadrada no basta con hacer x>y para comprobar la direccion del vector, deberás usar un cálculo trigonométrico o aceptar que habrá fallos.

O usar el truco 2: Asegurate que la caja es el doble de ancha que de alta y divide por 2 la componente horizontal del vector. Ale, ya tienes un espacio vectorial cuadrado en vez de rectangular. En general escalas x por la relacion ancho/alto de la caja, si lo que quieres es evitar trigonometría.

No se si ha quedado claro o no.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.