La están peinando…

Estamos en la fase final del juego. Todo el codigo funciona perfectamente ya, la lista de bugs esta clara y contenida, y es tiempo de retocar y mejorar cosas y hacerlo más gracioso. Estamos repasando todos los niveles retocandolos estética y funcionalmente para hacer una curva de dificultad lógica y equilibrada. Las 3 áreas por donde transcurre el juego tienen diferencias de comportamiento:

• El templo: La bola cae solo por los agujeros, normalmente se puede apoyar en paredes y demás
• Las minas: La bola se cae fuera del camino, pero hay un carril que ayuda a mantenerla en su sitio.
• La selva: La bola se cae fuera del camino, y no hay ninguna ayuda para mantenerla.

A partir de estas 3 clases, estamos haciendo unos niveles base y algunos que son combinaciones de los básicos en función de de trampas y efectos.
Y estamos metiendo los toques extra que diferencia a un juego de otro, los detalles y las chorradas.Por ejemplo, la antigua y fea pantalla de las plataformas, ahora contiene el majestuoso trono de Mah-Trakka, con el emblema de la Mosca Aúrea, animal sagrado, grabado en el respaldo.

Image

El botón para cambiar la vista de cámara ya tiene su iconito y todo. La salida  del templo tambien ha sufrido cambios. El inane escenario antiguo ha sido decorado con reproducciones del Demonio Goh-Ron y carteles para facilitar su visita, ademas de mejoras en la resolución de las texturas y railes. Pongo el antiguo y el nuevo. No vamos a poner muchos más para no chafar todas las sorpresas, paladeadlos.
cueva

capturanueva1

 

[edito] Añadimos un pantallazo de la nueva selva, para que haya un representante de cada nivel (templo, minas y selva):
capturanueva3

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.

Algunos trucos sucios

Vamos a contaros ahora algunos de los sucios trucos que hemos usado con el noble fin de trabajar menos o sortear problemas que nos costaría mucho resolver de forma mas «limpia».
Como comentaba en otro post el explorador tiene velocidad variable, corre más cuando la roca esta cerca. Esto tiene dos objetivos:

-Por una parte, hacerlo más divertido y «realista»
-Por otra, dar más margen y libertad de juego. Supongamos que el explorador tardase de forma fija 30 segundos en recorrer el laberinto, entonces solo tendríamos ese tiempo para resolverlo antes de aparecer el mensaje de fin de partida, y resultaría frustrante, no tendríamos tiempo para acostumbrarnos, sobre todo en fases complicadas y tendria un comportamiento muy rígido.

Hemos hecho que el mangante deje de acelerarse al tener la roca cerca cuando se encuentre a cierta distancia de la salida. Antes de que llegue a ese punto, correrá tanto que será imposible cazarlo.
Así, un jugador experimentado puede acabar la pantalla en los 30 segundos mencionados antes, con el explorador corriendo a toda leche, pero un jugador novato podrá acabarla en (pongamos) un minuto atascándose por el camino, con el explorador corriendo despacio. En la practica funciona como un temporizador con un máximo y un mínimo. Por eso el consejo para pasar las pantallas es sobre todo centrarse en resolver el laberinto sin intentar chafar al tipo antes de tiempo.

Programar es como descabezar una Hidra, cuando  resuelves un problema aparecen 3 nuevos. Por ejemplo, en la fase del molino, el tema de sincronizar el giro de las aspas con la vagoneta para evitar que se golpeen seria facil si la velocidad fuera fija, pero no sabemos cuando va a llegar el personaje a las aspas para ajustar su giro. La forma más sencilla que hemos encontrado es algo parecido al truco de la visión de aquel post, poniendo unos objetos invisibles pegados a las aspas.  En la siguiente imagen los hemos hecho activado para que se vean, los que están pintados en blanco, hacen que el molino acelere al colisionar con la vagoneta, los amarillos, que frene. Así evitamos que choque con ella. Es un truco sucio pero no se nos ha ocurrido otra forma de hacerlo.
detectores

La siguiente jugarreta avergüenza al diseñador pero tendrá que vivir con ello. Durante las fases de las minas, el explorador pasa de ir corriendo a montar en una vagoneta. Le pedimos que hiciera una animación de forma que saltara dentro y se pusiera en marcha y ¿que nos entrego? El personaje se mete en una cueva y vuelve a aparecer ya montado y se ahorró todo el curro de animarlo. Se aprovecha de que no puedo rebajarle el sueldo (no tiene)
cueva

El siguiente truco es sensato y se usa mucho en juegos, utilizar colisionadores sencillos ocultos bajo formas complejas que en realidad no afectan. En nuestro caso, a veces aparecen unos esqueletos de antiguos saqueadores sin fortuna que entorpecen la marcha de la roca. Los huesos en realidad no afectan a la bola, sino unas pirámides que hay ocultas en su misma posición. Esto hace que las físicas sean mas rápidas porque al procesador le cuesta menos calcular las colisiones de la bola con objetos sencillos (como las pirámides) que con objetos complicados como los huesos con sus recovecos y esquinas. En la siguiente foto hemos apagado el esqueleto de la derecha e  iluminado las pirámides para que las veáis. En los juegos, como en la tele, todo es mentira.

esqel

Ale, ya os contaremos más problemas que nos hemos encontrado, por desgracia hay material para muchos posts, hasta luego.

Programando el miedo

El movimiento del personaje se basa en una serie de puntos (waypoints) sobre el escenario que va recorriendo por orden. Al principio los recorría sin más, un punto tras otro. Para evitar el problema de que la bola lo adelantara y se dirigiera hacia ella (lo que no dejaría en buen lugar su inteligencia) habíamos pensado en hacer los escenarios de forma que el recorrido fuera lineal, sin la posibilidad de que la bola pudiera adelantarle sin chafarlo.

Luego decidimos que si veía la roca delante pudiera girarse para esquivarla. Eso evitaría que se comportara como un robot, y así también podíamos hacer escenarios más abiertos y añadía jugabilidad y diversión al hacer al ladrón capaz de esquivar la bola en cierta medida. ¿como hacer que ind… perdón, el mangante viera la roca? Lo primero que pensamos fue en complicados algoritmos basados en la distancia, orientación, etc. pero al diseñador se le ocurrió una solución mucho más sencilla. Creamos un objeto triangular y lo pegamos al personaje haciendo que detectara la colisión con la bola. Este objeto seria invisible y ademas de permitir una programación muy sencilla podíamos cambiar su ancho y largo fácilmente para hacer que el personaje viera mas lejos o mas «ámplio». Si el campo de visión chocaba con la bola, sencillamente decíamos que el próximo waypoint fuera el anterior en vez de el siguiente en su lista. Añadimos un punto extra al que solo se dirigiría si hubiera llegado al primero para evitar un movimiento de ping pong si no quedaban waypoints anteriores. Se puede ver claramente en el siguiente vídeo, donde hemos iluminado el objeto campo de visión en verde.
Ademas, también se aprecia bien otro comportamiento añadido para que sea mas gracioso y dinámico, corre más cuando la roca esta cerca, ampliaremos la información sobre esto en otro post.

Al principio fue el pixel…

En la primera reunión del equipo teníamos que decidir que juego hacíamos como primer proyecto. Tenia que reunir una serie de características, entre otras las siguientes:
• Ser sencillo: Un juego que pudiéramos afrontar con conocimientos básicos (era nuestro primer juego para todos) y que no corriéramos peligro de atascarnos por problemas técnicos.
• Ser de desarrollo rápido  Que no se convirtiera en un desarrollo de muchos meses, el objetivo era ganar experiencia global de forma rápida sobre todos los aspectos de publicación de un juego. Ademas somos un equipo muy pequeño (no puede ser mas pequeño, de hecho) y no nos podíamos liar a hacer miles de texturas, modelos, etc. esta característica se fue al garete al final por diversas cuestiones, llevamos bastantes meses. Otra razon para un desarrollo breve es que por inexperiencia se comenten errores en el codigo que en un juego corto no causan gran problema pero pueden lastrar un juego largo.
• Jugabilidad probada: No se trataba de innovar en ningún aspecto sino de aprender sobre bases solidas.
Decidimos hacer un juego típico de bola en laberinto, de los que hay cientos. Es una mecánica de jugabilidad probada y nos permitiría además coger experiencia en simulaciones físicas. Para no hacer un mero clon como tantos otros había que darle una vuelta que le diera un punto especial. Ese punto especial lo dimos haciendo que el objetivo no fuera solo sobrevivir en el laberinto sino aplastar a una pobre victima que trataba de escapar de la bola. Eso añadía también el morbo de ver un bicho corriendo por su vida mientras tratas de aniquilarlo. Como argumento, cogimos el típico de Indiana Jones huyendo de la roca, que también ha sido empleado en muchos juegos desde la película original pero (que sepamos) nunca desde la óptica de la roca, intercambiando los roles de «bueno» y «malo». Así se convertía también en un juego original e interesante.
El primer prototipo lo hicimos con Blender, la herramienta que usamos para el modelado 3D, que dispone de un motor de físicas y un generador de ejecutables para hacer juegos. Así podíamos tener una vista inicial de las características del juego y ver si era interesante y tenia posibilidades. Hemos rescatado dicho ejecutable y grabado un vídeo para enseñároslo, podemos considerarlo una ecografia de Mah-Trakka en su versión 0.000001, cuando apenas había sido engendrado (un descuido…).

Ahora una foto de la victima de cerca, que en el vídeo anterior  no se ve muy bien. Se puede ver que era prácticamente un imberbe mozalbete comparado con el madurito interesante y barbudo de la actualidad, ha crecido mucho comparado con su aspecto de hoy en día en la cabecera del blog.
indiprimer

Y a continuación el vídeo en su estado actual, para las odiosas comparaciones. En realidad este vídeo tiene algunas semanas y ahora incorpora cosas como las luces dinámicas que comentábamos en el anterior post:

Un problema tonto y su solución tonta.

He pedido al programador que nos escriba unas lineas sobre algún aspecto del juego que le pueda parecer interesante para comentaros. Os traslado sus impresiones:

«Hombre, voy muy mal de tiempo, pero en fin.
Hemos tenido un pequeño problema con la cámara . Al principio el juego no contemplaba scroll, la cámara estaba fija en una posición cenital y ya está, no había problema. Después, se planteo la idea de hacer un scroll vertical para poder dar mas enjundia a las fases haciéndolas más grandes. Para mover el scroll se tomo la posición en pantalla de la bola, si estaba mas arriba del primer tercio  de la pantalla, la cámara se desplazaba hacia arriba para centrarla, mas abajo de 2 tercios, en el sentido contrario. si estaba en el tercio intermedio, se desactivaba para no marear ni afectar el rendimiento.  En las escenas cuya habitación «cabe» en la pantalla, se desactiva

Pero se planteó el siguiente problema, si nos limitábamos a mover el eje z de la cámara podía «chocar» contra el suelo como se ve en el siguiente gráfico, que esta tomado desde una vista XY, que en el argot técnico llamamos «de lado».

poblema

Lo que hice fue emparentar (ligar, atar) un objeto intermedio invisible (el cuadrado rojo) a la superficie del laberinto, y emparentar la cámara a este objeto. Cuando hiciera falta hacer scroll según la norma de los tercios anterior el objeto intermedio se movería en consecuencia sobre el eje Z de las coordenadas del laberinto y la cámara lo sigue, manteniendo siempre la misma distancia y orientación relativa sobre el plano del laberinto de forma sencilla y facil de programar.
Es posible que en siguiente gráfico se aprecie mejor lo que quiero decir.

solucion