Ir al contenido principal

Quiéres estos diseños en tu ropa o en diferentes productos?

Publicidad

Colisiones con Love2D, rectángulos, círculos, triángulos


En todo proceso de desarrollo de videojuegos se requiere verificar si algún punto o coordenada está dentro de una área especifica de la pantalla y así reaccionar a ese caso, como puede ser que el puntero del ratón este dentro del área de un botón y que al hacer clic se ejecute alguna acción, o que el disparo del enemigo este dentro del rectángulo que limita a nuestro jugador. A este proceso comúnmente se le llama detección de colisiones y existen distintos algoritmos que nos facilitan esta tarea, hoy te mostraré como verificar las colisiones entre rectángulos, círculos y triángulos.

Detección de un punto dentro de un rectángulo.

Verificar si un punto está dentro de un rectángulo es bastante sencillo, basta con comparar las coordenadas de nuestro punto con las coordenadas mínimas y máximas de nuestro rectángulo y verificar que está dentro de esos valores. Veamos la imagen.

En la imagen podemos observar las 4 coordenadas del rectángulo que necesitaremos, los valores de "x1" e "y1" ya lo conocemos debido a que es el valor que pasamos a Love2D para que dibuje en la pantalla, si queremos dibujar una imagen usamos love.graphics.draw(imagen,x,y), "x" e "y" son justamente los valores de "x1" y "y1" en el caso de la imagen. Bien para obtener el valor de las coordenadas "x2" e "y2" solo sumamos a las coordenadas de origen el ancho y alto del rectángulo, quedando entonces los valores de esta manera. 

x2 = x1 + ancho

y2 = y1 + alto

Ya teniendo estos valores mínimos y máximos del rectángulo, solo nos queda comparar el valor de las coordenadas del punto con los valores de las coordenadas del rectángulo. La comparación en simples palabras sería así, si la coordenada "x" del punto está dentro de "x1" y "x2" (es decir que el valor "x" del punto es mayor que "x1" y menor que "x2"). Y si la coordenada "y" del punto está dentro de "y1" e "y2" entonces podemos afirmar que ha habido una colisión. La comparación en nuestro código quedaría así.

if x1 <= x and x <= x2 and y1 <= y and y <= y2 then

    -- hay una colisión!

end

Segundo método de detección de colisiones en rectángulos.

También es posible detectar la colisión calculando la distancia entre el punto y el centro del rectángulo. Si tomamos la coordenada "x" del punto y la coordenada "x" del centro del rectángulo  y restamos ambos valores obtenemos la distancia entre ellos, y si ese valor es menor o igual a la mitad del ancho en el caso de las coordenadas "x" podemos decir que también hay una colisión, obviamente si también se cumple en la coordenada "y". Veamos como hacer este cálculo.

Las coordenadas del centro del rectángulo se calculan de esta manera, dividimos el ancho entre dos y la sumamos al origen.

rcx = x1 + ancho * 0.5

rcy = y1 + alto * 0.5

Luego restamos los valores de las coordenadas del punto con las coordenadas del centro del rectángulo, aplicamos la función de Lua abs() para obtener el valor absoluto de la resta, y esto se hace para no obtener valores negativos del cálculo.

distx = math.abs(rcx - x)

disty = math.abs(rcy - y)

Teniendo la distancia entre las coordenadas solo nos queda comparar estos valores con la mitad del ancho y la mitad del alto del rectángulo, y si las distancias son menores que el ancho y alto tenemos la colisión.

if distx <= ancho * 0.5 and disty <= alto * 0.5 then

    --tenemos colisión

end

Detección de un punto dentro de un círculo.

 
 
El método para detectar si hay un punto dentro de un círculo es parecido al segundo método para verificarlo en un rectángulo necesitándose igualmente calcular la distancia del punto con el centro de la figura, en este caso la ecuación de la distancia es distinto y solo tenemos como ancho o alto el radio del círculo. Para realizar el cálculo de la distancia es necesario utilizar un triángulo y la fórmula del teorema de Pitágoras para calcular el lado que necesitamos que en este caso sería la hipotenusa.

Los valores de "dx" y "dy" ya sabemos como calcularlos, siendo estos las diferencias entre las coordenadas del círculo y el punto.

dx = math.abs(cx - x)
dy = math.abs(cy - y)

Y para obtener la distancia usamos la ecuación siguiente:

dist² = dx² + dy² 
 
Eliminando la potencia de la variable dist la ecuación final es.
 
dist = √(dx² + dy²)
 
El código en Lua.
 
dist = math.sqrt( math.pow(dx,2) + math.pow(dy,2))
 
Y de esta manera obtenemos el valor de la distancia, lo que nos queda es comparar, con el radio del círculo y si el valor de la distancia es menor entonces el punto está dentro del círculo.

if dist <= radio then
    --hay una colisión
end

Detección de un punto dentro de un triángulo.

El cálculo de un punto dentro de un triángulo es muy distinto a los anteriores, en este caso utilizaremos el área de triángulos para así compararlos y verificar si el punto está dentro del triángulo.
 
La idea es la siguiente, teniendo un triángulo cualquiera y tomando un punto dentro de él formamos triángulos a partir de ese punto y los vértices del triángulo, la suma de las áreas de esos triángulos internos será igual al área del triángulo externo, solamente si el punto está dentro del área de la figura.
 

 A = A1 + A2 + A3
 
Pues entonces tomando el punto que deseemos verificar si está en colisión con el triángulo, y creamos triángulos con los extremos del triángulo principal obteniéndose así tres triángulos de los cuales calcularemos sus áreas y las sumaremos, si el valor obtenido es igual al valor del área del triángulo principal entonces el punto estará dentro del triángulo.
 

 Para calcular el área de los triángulos usaremos la siguiente ecuación:
 
A = math.abs( (x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1) )

Con esta fórmula no estamos calculando directamente el área del triángulo que buscamos, sino el área de los triángulos rectángulos que se forman a su alrededor (usando la fórmula A = base * altura), que luego restamos como vemos en la fórmula y el valor resultante es el área del triángulo central como podemos ver en la figura siguiente, las áreas coloreadas son los calculados en la ecuación y su resta nos da el área central.


Aplicando este mismo método a los triángulos formados por los vértices del triángulo y el punto a verificar, nos quedan las siguientes ecuaciones.

a1 = math.abs( (x1 - px)*(y3 - py) - (x2 - px)*(y1 - py) )

a2 = math.abs( (x2 - px)*(y2 - py) - (x3 - px)*(y2 - py) )

a3 = math.abs( (x3 - px)*(y1 - py) - (x1 - px)*(y3 - py) ) 

"px" y "py" son las coordenadas del punto. Y solo nos queda sumar y comparar.

if (a1+a2+a3) == A then

    --hay colisión

end

En el siguiente video se pueden ver los tres métodos de colisión en funcionamiento.

Para dibujar un triángulo o cualquier polígono con Love2D usamos la función love.graphics.polygon("fill o line",x1,y1,x2,y2,x3,y3,....), puedes agregar cuantos puntos necesites siguiendo esa regla, también puedes pasarle como parámetro de coordenadas una tabla, polygon("fill o line", {x1,y1,x2,y2,x3,y3}).

Si deseas el código de esta práctica lo tienes aquí.

Eso es todo por los momentos espero lo hayas comprendido y puedas aplicarlo en tus prácticas.

Si te pareció útil me ayudarías mucho compartiéndolo. 

Hasta la próxima.

Comentarios

  1. ¡Increibe!, No conocía el algoritmo de colisión del triangulo, normalmente cuando se habla de colisiones simples solo se limitan a hablar del circulo y el cuadrado, posteriormente sobre como llenar tu personaje de cuadros y circulos.
    ¡Gracias por compartir!

    ResponderEliminar

Publicar un comentario