Algunas nociones sencillas de matemáticas en programación.

Las viejas matemáticas simplonas, los problemas que nos dieron en la EGB (a los que ahora somos viejos y caducos) y los problemas que nos resuelven ahora. Por ejemplo, los botones para conmutar estados. Nos gusta reducir al mínimo los condicionales (if … then…) para reducir el código y hacerlo mas legible. Pongamos que tenemos un botón que active o desactive cierto estado, podemos hacerlo así, suponiendo que el estado pueda ser 1 o 0  (pongo código «inventado» para facilitar la comprensión, la sintaxis de javascript en unity es muy distinta)
if pulsarboton {
if (estado=1) then (estado=0) else (estado=1)
}

Pero recordemos que según las matemáticas esas, positivo * positivo=positivo, positivo*negativo= negativo y negativo * negativo= positivo, así que podemos simplificar el código si dejamos los posibles estados como 1 y -1 en vez de cero, y al pulsar el botón se multiplica por -1, quedaría de esta manera:
if pulsarboton {
estado= estado *-1
}

Y se conmuta el estado automáticamente de forma un poco más sencilla y sin bucles «if». Otro truco para evitar condicionales es usando la propiedad de que  cualquier numero multiplicado por cero es igual a cero. Pongamos que tenemos una variable x que se incremente o decremente al pulsar los botones de izquierda-derecha para menear un personaje, podemos hacerlo así.
if pulsarizq=1 {
x=x-5
}
if pulsarder=1{
x=x+5
}

Pero podemos simplificarlo así en una sola linea sin «ifs»:
x=x+(5*pulsarder)-(5*pulsarizq)

Si uno de los dos valores es 1 se realizara la suma/resta, sino, sumara cero y no se moverá. Si queremos añadir inercia para hacer el movimiento más natural, o simular que el personaje anda sobre el hielo, no variaremos directamente la posición x del personaje, sino que cambiaremos su aceleración con una variable intermedia.
acel=acel+(5*pulsarder)-(5*pulsarizq)
x=x+acel

Si queremos que el personaje frene si no se pulsan los botones, hay que hacer que ac tienda a cero añadiendo algo como lo siguiente:
acel=acel/2

Y ademas hacer que la aceleración se convierta en cero si es muy pequeña
if (acel*acel)<0.4 {
acel=0
}

Usamos el cuadrado de ac para convertir su valor en positivo y evitar dos condicionales, uno si es positivo y otro si es negativo. Con el truco anterior, aun podemos eliminar el if y juntar todo lo anterior haciendo esto:
acel=(acel/2)*((acel*acel)>0.4)+(5*pulsarder)-(5*pulsarizq)

De esta forma, si acel al cuadrado es menor que 0.4, la comparación devuelve cero (false) que al multiplicar por la aceleración anula esta, y hemos incluido también el control y el frenado sin tener que utilizar ni un solo bucle if y en una sola linea. Nuestro programador es un crack. Espero que no se entere la competencia y le llame.
Cambiando los distintos valores, haremos que el personaje acelere o frene mas rápido, pudiendo simular que camina sobre tierra, hielo, manchas de aceite, etc.

Otro caso que nos ha ocurrido recientemente, aunque en otra aplicación, no en este juego, demuestra que mucha veces es mejor gastar el tiempo buscando el camino más sencillo que torturando una solución complicada para que funcione. Es un juego en el que podemos colocar en cualquier posición una muñeca articulada en 2d, una especie de marioneta. Queríamos que al mover la mano, la combinación brazo-antebrazo se moviera de forma natural siguiéndola, lo que se conoce como  cinemática inversa (IK) en animación. Estuvimos probando pluguins y código ajeno, pero eran muy complicados porque estaban preparados para múltiples articulaciones en un escenario 3D, nos rompimos la cabeza intentado simplificar el código para limitar la rotación solo en un eje sin mucho éxito, hasta que nos dimos cuenta que en realidad, estábamos hablando de resolver los ángulos de un triangulo conocidos la longitud de los tres lados (el brazo, el antebrazo y la distancia entre la mano y el hombro), que como todo el mundo sabe (después de buscar en internet)  sigue la siguiente formula:

triangulosAsí (usando la inversa del coseno) sabemos en que angulo tenemos que girar los objetos que forman el brazo y el antebrazo. Con un par de ajustes funciona perfecta y rápidamente  sin usar complicados algoritmos.

Bueno, igual todo esto le sirve a alguien, se puede aplicar a cualquier lenguaje de programación con los debidos retoques, seguimos en contacto, adeu.

Deja un comentario