viernes, 14 de junio de 2013

Crea tu juego indie - Anexo - Matemáticas (1)

Sí amigos, esta es una de esas partes desagradables que tarde o temprano tenía que tocar. Sin embargo, no vamos a centrarnos en los fundamentos que hay por debajo o su implementación (que para eso ya está implementado y optimizado en Unity y en casi cualquier otro motor que decidáis utilizar), sino en su utilidad práctica; cómo sacar ventaja de estas funcionalidades para entender mejor cómo funciona un juego y ser mucho más productivos y versátiles. Con saber que existen y qué hacen es más que suficiente.

Hoy empezaremos por la clase fundamental de matemáticas en Unity: Mathf.

Mathf

Mathf es la clase de Unity encargada de ofrecernos la funcionalidad básica para el cálculo con números decimales (float).

Constantes

En Mathf se definen una serie de valores constantes:
  • PI: El archiconocidísimo número 3.14159... Relaciona el radio de una circunferencia con su longitud o el área de su círculo. Es útil para trabajar con ángulos en radianes, por ejemplo.
  • Deg2Rad y Rad2Deg: Son dos constantes para convertir un número de grados a radianes y de radianes a grados, respectivamente. Como la relación entre grados y radianes es la misma siempre, pueden precalcularse (como en este caso). Para usarlos, basta con multiplicar el ángulo (en grados o en radianes) por la constante correspondiente para cambiarlos a la otra unidad. Por ejemplo:
    // Convertir 70 grados a radianes
    var anguloEnRadianes = 70.0 * Mathf.Deg2Rad;
    // Pi radianes = 180 grados
    var anguloEnGrados = Mathf.PI * Mathf.Rad2Deg;
    En ocasiones podremos encontrarnos librerías que sólo trabajan con una de las dos unidades, y será necesario hacer la conversión.
  • Infinity, NegativeInfinity y Epsilon: El número más grande positivo, el más grande negativo, y el más pequeño, respectivamente, que pueden almacenarse en un float. Los infinitos vienen muy bien para inicializar valores (por ejemplo, si quieres asegurarte de que el primer número que compares sea siempre menor que el valor por defecto, etc.). Épsilon es bastante útil si se quiere evitar una división por cero (y además, si se suma épsilon a un valor distinto de cero, ese valor no cambia, de manera que es seguro utilizarlo).

Signo y valor absoluto

  • Sign(x): Es una función que devuelve el signo de un número X, como un número 1 si X es positivo o -1 si X es negativo.
  • Abs(x): Esta función devuelve el valor absoluto de un número X (el valor de X sin su signo).

Comparación de números

  • Min(a,b) y Max(a,b): Comparan A y B, y devuelven el menor y el mayor de los dos, respectivamente. Por poner uno de los muchísimos ejemplos, si una IA tuviera que decidir a cuál de varios objetivos atacar según sus puntos de vida restantes.
  • Approximately(a,b): Compara A y B para ver si son casi iguales. Cuando se va a comparar que dos números decimales, por cuestiones de precisión, se debería usar esta función en vez de el comparador ==.

Redondeo

  • Round(x): Redondea X al número entero más cercano.
  • Floor(x) y Ceil(x): Redondean X estrictamente hacia abajo o hacia arriba.
Estas tres funciones son bastante útiles al trabajar con cuadrículas, por ejemplo.

Potencias y logaritmos

  • Pow(x,y) y Exp(y): El valor de multiplicar un número (X y la constante e, respectivamente) por sí mismo Y veces.
  • Sqrt(x): La raíz cuadrada de X. En otras palabras, el número que multiplicado por sí mismo vale X.
  • Log10(x), Log(x) y Log(x,b): El número al que hay que elevar la base (10, e y B, respectivamente) para obtener X. Es la inversa de las potencias (Log(Exp(x)) == x, Log(Pow(x,n),n) == x).
No tienen mucha utilidad, salvo hacer algunas implementaciones a bajo nivel por nuestra cuenta. Por ejemplo, las funciones ClosestPowerOfTwo(x), IsPowerOfTwo(x) y NextPowerOfTwo(x), que se usan sobre todo para trabajar a bajo nivel con texturas, las utilizan.

Trigonometría

  • Sin(x) y Cos(x): Devuelven respectivamente el seno y el coseno de X. Son increíblemente útiles. De entrada, por su naturaleza oscilante, se pueden usar para ciertas animaciones (enemigos que flotan hacia arriba y hacia abajo, volando alrededor de un punto en círculo, o como un pendulo). Además, son cíclicos y contínuos, y tienen mucha utilidad con patrones que se repiten (generar texturas fractales, valores aleatorios "repetibles" como el ruido Perlin...)
  • Tan(x): Devuelve la tangente de X.
  • Asin(x), Acos(x) y Atan(x): El arco-seno, el arco-coseno y la arco-tangente. Devuelven el ángulo tal que su seno, su coseno y su tangente (respectivamente) son X. Atan2(x,y) es una variante de Atan(x) que recibe las longitudes de los catetos (las componentes de un vector 2D) en vez del valor de la tangente.
Salvo el caso del seno y el coseno, el resto sólo se utilizan con frecuencia cuando se van a hacer cálculos a bajo nivel. En realidad casi todos sus usos están en otras implementaciones ya ofrecidas por Unity.
Hay que tener en cuenta que todos los ángulos que utilizan están en radianes.

Acotación

  • Clamp(x,a,b): Devuelve el valor de X recortado a un mínimo de A y un máximo de B. En otras palabras: si X es menor que A devuelve A, si X está entre A y B devuelve X, y si X es mayor que B, devuelve B. Por ejemplo si tras calcular daños y curaciones, queremos asegurarnos de que la vida del jugador no se sale de un cierto rango. Clamp01(x) es equivalente a Clamp(x,0,1).

Interpolación y otras funciones predefinidas

  • Lerp(a,b,t): Calcula el punto intermedio entre A y B, a una distancia relativa T. Si T == 0, devuelve A. Si T == 1, devuelve B. Si T == 0.5, devuelve la media exacta entre A y B. Calcula los valores intermedios interpolando linearmente. En estas gráficas se pude ver los valores de Lerp(0,1,x) en rojo y Lerp(3,0.5,x) en verde.
    • LerpAngle(a,b,t): Es similar a Lerp(a,b,t), salvo que está preparado para ángulos. Si se usa Lerp(350,10,x), va bajando de 350 hasta 10. Si se usa LerpAngle(350,10,x), pasará por 360 grados, continuando desde 0 grados.
    • InverseLerp(a,b,x): Es la inversa de Lerp(a,b,t). Devuelve la posición relativa de X entre A y B (0 si X==A, 1 si X==B).
  • SmoothStep(a,b,t): Es similar a Lerp(a,b,t), pero con una aceleración inicial y deceleración final, para suavizar el movimiento, en vez de usar una interpolación lineal (más brusca al empezar y parar). Aquí están los ejemplos usados en Lerp, pero usando SmoothStep.
  • SmoothDamp(...): Va cambiando un valor gradualmente hacia otro de forma suavizada (decelerando cuanto más se acerca al final). Es muy utilizado al animar cámaras, entre otros casos. SmoothDampAngle(...) es la versión especializada para ángulos.
  • Repeat(x,n): Cuando X > N, empieza de cero de nuevo. Se usa, por ejemplo, cuando se quiere que los valores se repitan de 0 a N. Por ejemplo, la gráfica de Repeat(x,1.7)
  • PingPong(x,n): Similar a Repeat(x,n), pero los valores van subiendo y bajando de 0 a N. La gráfica resultante sería como un diente de sierra (aquí la gráfica de PingPong(x,2))
  • DeltaAngle(a,b): La diferencia menor entre dos ángulos determinados A y B. Cíclicos en 360 grados, y devuelve el menor entre la diferencia de ángulos en sentido de las agujas del reloj y en sentido contrario.
  • PerlinNoise(x,y): Usa una combinación de varias funciones (normalmente trigonométricas, pero depende de la implementación) para generar una textura repetible y pseudo-aleatoria (en este caso, se devuelve el valor de esa "textura" en el punto (X, Y)). Su uso original era el de generar texturas, pero se puede usar para infinidad de cosas más (como aleatorizar mazmorras o crear terrenos mediante algoritmos). Para que os hagáis una idea de su utilidad para todo lo multimedia, en 1997 a su creador, Ken Perlin, le dieron un Oscar por logros técnicos por inventar este y otros métodos similares.
  • MoveTowards(x,y,max): Calcula la interpolación lineal de X a Y, pero sin superar una distancia máxima. Una especie de "limitador de velocidad" en la interpolación. MoveTowardsAngle(x,y,max) es similar, especializada para ángulos.

        No hay comentarios:

        Publicar un comentario