No Más Curvas.

Abandonada la curva Bezier para el desplazo de enemigos.

Por más que intenté hacer que esas curvas se sintieran reales y divertidas, siempre fallaba. Cada intento se volvía un desafío, ya que el arte de crear juegos es mucho más complejo de lo que parece a simple vista. Además de que no era fácil imitar el concepto original de «Space Invaders» y «Galaga», en que los enemigos se alinean en formación.

La dificultad radicaba no solo en replicar la esencia de esos clásicos, sino en darle un giro moderno. Sin embargo, a pesar de mis mayores esfuerzos, sentía que algo siempre faltaba para captar la atención del jugador y hacer que se quedara inmerso en el juego.

Seno, Coseno y Tangente

Encontré la solución en la trigonometría básica. En vez de desplazar los enemigos a través de una compleja curva Bézier, ahora solo calculo sus posiciones basadas en un ángulo y radio.

    public static float shortestAngularRoute(float fromAngle, float toAngle) {

        // Angular chase mechanics.

        // This is the canonical and best way to calculate the shortest
        // signed angular distance between two angles, ensuring the result
        // is in the range (−π,π] radians.

        return MathUtils.atan2(
            MathUtils.sin(toAngle - fromAngle),
            MathUtils.cos(toAngle - fromAngle));
    }

Por ahora, solo escojo un ángulo al azar y hago que el enemigo constantemente persiga ese ángulo como destino.

Hay algunos asuntos importantes a considerar al implementar la mecánica de persecución que involucra ángulos de dirección. El primero es que, al trabajar con ángulos en radianes, calcular la dirección de movimiento que resulta en la ruta más corta requiere un poco más de esfuerzo que simplemente comparar dos valores angulares.

Específicamente, para conseguir la distancia angular más cercana, tienes que considerar cuándo la ruta más corta implica cruzar el límite del ángulo cero (o 2π radianes). Es decir, el cálculo debe determinar si es más eficiente girar en sentido horario o antihorario para alcanzar el ángulo objetivo.

Otro asunto muy importante es la comparación de variables de punto flotante «float». Por su naturaleza, no es eficiente una simple comparación y determinar si el enemigo ya alcanzo el ángulo destino. Para lograr comparar este tipo de variables es necesario usar un épsilon como limite.

return Math.abs(destinyAngle - currentAngle) <= epsilon;

Epsilon es otra variable de punto flotante que actúa como límite para la comparación. Aun así, también es necesario asegurar que el ángulo que se está moviendo (basado en una velocidad) hacia el ángulo destino, también está limitado a 2π radianes para asegurar que la comparación funcione.

    public static float normalizeAngle(float angle) {
        float normalizedAngle = angle % MathUtils.PI2;
        if (normalizedAngle < 0) normalizedAngle += MathUtils.PI2;
        return normalizedAngle;
    }

En conclusión, usando angulo, radio, mecánica de persecución y comparación con epsilon remplace el concepto de curvas bezier y resulto en algo mucho mejor y mas fiel al concepto original.

Y asi se ve:

Únete a otros 36 suscriptores

Deja una respuesta

Anuncios


Consola en pantalla 

Algo que siempre he querido tener es la consola visual en pantalla. Lo encuentro útil porque puedo ver el evento directo sin tener que desviar la mirada hacia la consola.

Continua Leyendo…
Anuncios