Dev++

28 de febrero, 2014
Desarrollo Dirigido por Pruebas en videojuegos

Cuando desarrollar juegos pasa de sueño a pesadilla tienes varias alternativas. Una de las mejores es preguntarle a un japonés que haya trabajado en Toyota y probablemente te hablará de tener el coraje de parar, de pensar a largo plazo y buscar una solución que te lleve de vuelta al cielo sin escalas. Pero como no tenía ningún japonés cerca tuve que buscar mi propia solución. Esta es mi experiencia como desarrollador de juegos aficionado. Pasen, pasen y lean.

Javier Gutiérrez (@IWT2_Javier en Twitter) es doctor en lenguajes y sistemas informáticos, y enseña e investiga en la Universidad de Sevilla. En el mundo de los videojuegos participa esporádicamente en algunas game jams, colabora con GameUS, un pequeño club que tiene como objetivo animar a que todo el que tenga interés comience a crear sus propios juegos. Además imparte charlas sobre desarrollo de videojuegos con TDD como a la que vamos a asistir hoy. También es conocido con el hombre donut por su afición de plantarse en empresas y grupos de desarrollo de juegos con una caja de donuts como excusa para interesarse por los pequeños equipos de desarrollo que luchan por sobrevivir.

Welcome to Game Jam’s Hell

A finales de 2012, participé en la F*CK This Jam, una jam que nos dejó algunas piezas tan buenas como la parodia del simulador de paseos bucólicos Dear Esther, llamado Dear Esteban. creado por URSA, o el simulador de juego de mesa Desperate Gods, de Wolfire. El objetivo fue crear juegos de la temática que más odias. Porque, ya sabes… mi gato se quedó dormido sobre el teclado y se terminó Dear Esther. Yo en cambio no tuve duda de que mi destino era hacer el juego de plataformas que el mundo lleva treinta años esperando (¡que te den Mario!): Wanna Live? Run!

Mi experiencia creando Wanna Live? Run! fue horrible. Os la voy a contar para que nadie tenga que pasar por lo mismo o, si pasáis por ello, que sepáis que no estáis solos. Al principio todo iba bien. Escribía mucho código, ejecutaba el juego de vez en cuando, cambiaba cosas para simplificar las mecánicas del juego y todo avanzaba suave como la seda. Sin embargo, a medida que pasaban los días todo se fue volviendo más gris. Un día, probando el juego, descubro que hay un error que no había detectado al chocar con las plataformas. Lo corrijo y sigo adelante. Un rato después veo que hay otro error con los choques, ¿o es el mismo?. Bueno, lo corrijo y sigo adelante. Al día siguiente los choques siguen sin funcionar. Lo repaso y lo vuelvo a repasar; dedico mucho tiempo a pequeños cambios, ejecutar, mover el muñeco y volver a tocar el código y lo dejo perfecto… Hasta que al rato vuelve a fallar y no sé si es por algo nuevo que he implementado o por un error que ya estaba ahí y no había descubierto. Pero… ¡el código está bien! ¡lo prometo! Lo repaso y lo vuelvo a repasar y no veo nada mal. ¿Qué hago? Como NO SÉ qué falla, NO SÉ qué cambiar cambio cosas aleatoriamente, a ver qué pasa.

Las paradas y vueltas atrás eran constantes y sentía que no avanzaba en el juego. Cada vez que hacía un pequeño cambio tenía miedo a estropear algo que ya funcionaba, o a lo mejor hacía tiempo que no funcionaba y no lo sabía aún. Con muchísima frecuencia ejecutaba el juego y hacía la misma secuencia de movimientos. Esto era lento y muy, muy aburrido. Estaba haciendo chapuzas para salir del paso, lo cual fue un error porque al crear un juego no solo cambias cosas para arreglar fallos. Surgen nuevas ideas, descubres cosas que en el papel funcionaban muy bien pero una vez que las ves en marcha no funcionan, etc. Un juego SIEMPRE va a cambiar y todos los impedimentos y dificultades que pongamos a esos cambios, queriendo o sin querer, se volverán en nuestra contra y harán que nuestro juego no sea todo lo bueno que podría ser. (Por otro lado a veces demasiados cambios no vienen bien: Las primeras versiones del Gone Home eran geniales pero cambiaron).

También me sentía presionado por la fecha límite. De acuerdo, es una jam y si no terminas dentro del plazo límite no pasa nada, pero me había propuesto terminar en la fecha límite como reto personal y no quería fallar. Esta mal, cada vez le dedicaba más tiempo desatendiendo otras cosas e incluso no dormía bien. Finalmente fui capaz de entregar algo que se puede jugar y me sentí liberado de mi carga. Si después de todo lo que habéis leído, aún tenéis curiosidad lo podéis probar aquí: juega a Wanna Live? Run!

¿Por qué un hobby divertido se habría convertido en un simulador de trabajar en alguna de las mejores consultoras españolas? ¿Cómo podría resolver esto para futuras jams? Veamos una solución.

¡Test-driven development, sálvame!

No quiero más fallos inesperados, ni tener que cambiar cosas sin saber qué hacer, ni quedarme con cosas que no me gustan o complejas por miedo a cambiar y a estropear lo que tengo, ni consumir tiempo y energía ejecutando y volviendo a ejecutar y repitiendo secuencias de movimientos. ¿Cómo consigo no tener evitar estos problemas en la siguiente jam? En mi caso, la respuesta se llama Test-Driven DevelopmentTDD» a partir de ahora), o «desarrollo dirigido por pruebas» en español.

TDD es una técnica para escribir código que consiste en definir qué queremos que haga ese código antes de escribirlo. La manera de definir ese qué es escribiendo una prueba, de tal manera que si la prueba pasa con éxito, el código hace lo esperado. Veamos un ejemplo:

Tenemos una nave espacial que tiene unas coordenadas X e Y, y que el jugador puede mover con el teclado. Cuando el jugador pulse la flecha de la derecha, la nave debe cambiar su posición de una manera conocida de antemano y previsible. Es decir, si la nave está en la posición (30, 30), el movimiento a la derecha es +(10*delta) y delta es 0,1 entonces la nave debe colocarse en la posición (31, 30). Antes de escribir el código que mueve la nave a la derecha programamos los datos anteriores con una prueba. Cuando el código esté completo la prueba se ejecutará con éxito y sabremos que ya podemos pasar a otra cosa. Si más adelante me equivoco y, por ejemplo, cambio el desplazamiento de la nave a +(20*delta) la prueba me advertirá y sabré QUÉ está fallando, el movimiento a la derecha, y en qué parte del código tengo que mirar.

Ya no necesito ejecutar el juego constantemente ni repetir una aburrida secuencia de movimientos. Si introduzco algún error aunque sea sin darme cuenta, inmediatamente una o más pruebas fallan y puedo rastrear la causa del error, y además TDD garantiza un 32,7% menos de facepalms al ejecutar tu juego. ¿No es fabuloso?

Y después de toda esta charla, ¿cómo me ha ido aplicando TDD?

Mira mamá, ahora con TDD

El juego terminado que más tiempo de desarrollo me ha llevado hasta la fecha es Nelbe, hecho en Java y LibGDX para Android. Este juego lo hice para apoyar la campaña benéfica El Jardín de mi Hospi. En Nelbe apliqué TDD desde el primer minuto y todo fue mejor que con Wanna Live? Run!. Las pruebas verifican en mi lugar que los elementos se mueven correctamente y que colisionan bien. Además, las pruebas me ayudaron con las dependencias de los elementos, quién llama a quién y qué información deben conocer. Aplicar esta técnica no significa que todo salga fácilmente a la primera. Los errores siguen estando ahí pero, al menos, evito sorpresas.

Otro juego dónde apliqué dicho procedimiento fue Pick’A’Gem. Este juego fue una prueba en EasyJS y Javascript y cómo aplicar TDD en esta plataforma. De nuevo, utilicé TDD para verificar que los ficheros con las imágenes se hubieran cargado, para verificar los movimientos y para comprobar todo lo que tiene que pasar cuando una gema se pulsa. Si es la gema incorrecta suena un sonido, pero si es la gema correcta desaparece de la pantalla y se incrementa en uno el contador (si se pulsa en el espacio donde estaba la gema ya no pasa nada).

¡Voy con prisas!

Aplicar TDD hace que el desarrollo sea más lento, porque además de hacer el juego tienes que escribir muchas pruebas, más de 50 o 60 pruebas para juegos muy sencillos si quieres tenerlo casi todo controlado (Nelbe tuvo 89 solo para probar 1/3 del código). Pero yo lo veo como conducir. Llegas antes a tu destino si no respetas los semáforos, ni las señalizaciones y siempre vas por el camino más corto aunque sea en dirección contraria… pero las consecuencias de esas acciones pueden ser desastrosas. Sé que si dejo de hacer desarrollo dirigido por pruebas voy a obtener más velocidad a corto plazo, pero, a cambio, voy a perder el control de lo que está pasando en mi código y la red de seguridad que me va a salvar cuando las cosas vayan mal.

Conclusiones

TDD y la prueba automática de código son prácticas maduras en cualquier desarrollo de software y cada vez se va a ir utilizando más en el desarrollo de videojuegos. Mi opinión es que antes de empezar con TDD en el mundo de los videojuegos lo pruebes. Existen ejercicios específicos para aplicar desarrollo dirigido por pruebas que se llaman katas, algunas son muy sencillas y otras tienen más complejidad, por lo que puedes empezar por la que creas más adecuada. Ya bastante difícil es hacer un videojuego como para querer empezar con todo a la vez.

Las pruebas en el mundo de los videojuegos ha llegado para quedarse. Por ejemplo, Unity3D ya tiene una extensión oficial para desarrollar pruebas que puedes bajarte gratuitamente (con videotutorial incluído).

Existen varias comunidades en Internet con las que puedes hablar de TDD (ver enlaces más abajo), incluso existen reuniones periódicas en varias ciudades para hacer katas (como las artes marciales pero sobre programación) e intercambiar ideas y experiencia. Aunque no encuentres a nadie en tu ciudad, Internet está llena de katas que puedes utilizar para comparar tus propias soluciones.

También hemos visto que no todo es un camino de rosas. TDD es difícil es aplicar y a mí también me cuesta. Aún me resulta difícil pensar a priori lo que quiero hacer con el suficiente detalle como para escribir una prueba. También es difícil dividir el juego en partes lo más independientes posible para poder probarlas e ir escribiéndolas poco a poco. A menudo tengo que dar rodeos y dedicar tiempo para poder sortear ciertos escollos de las librerías que me dificultan la prueba. Pero, al final, esto hace que mi código sea de más calidad y hace de mi un programador mejor. Seguiré utilizando TDD para evitar volver al infierno.

Recursos y enlaces

A continuación tenéis algunas presentaciones y vídeos de charlas referentes a TDD y videojuegos que he impartido:

  • TDD y Videojuegos en Javascript
  • Desarrollo dirigido por pruebas para videojuegos
  • Programando juegos casuales con desarrollo dirigido por pruebas
  • Desarrollo de videojuegos dirigidos por pruebas
  • Un Sokoban con TDD paso a paso
  • En Sevilla, se organizan sesiones de prácticas y pruebas abiertas a todos en el IWT2 dojoUS
  • La experiencia de Crytek aplicando TDD
  • …y un resumen en español
  • Un artículo antiguo pero muy extenso sobre cómo aplicar TDD en videjuegos

Acerca de Dev++


Mi nombre es Dev++, pues somos muchos. indie-o-rama da cobijo a una legión de talentos del desarrollo que colaboran con su experiencia. Si no está hecho, puede hacerse. Si lo está, puede explicarse. Protagoniza el próximo Dev++ clicando aquí.

1 comentario