> Manuales > Taller de HTML5

5 Prácticas esenciales para crear juegos en HTML5… ¡en acción!.

HTML5 es extraordinario porque es versátil, no está orientado a un caso de uso específico. Lo más importante es que HTML5 es de uso universal. Está en el PC, en el teléfono, en las tabletas… y por lo que yo sé, un día podríamos tenerlo incluso en los electrodomésticos.

Juntando estas dos propiedades de HTML5 –su versatilidad y su universalidad- podemos ver claramente por qué muchos desarrolladores se sienten inspirados por esta tecnología. Y como dice el proverbio, "cuando los desarrolladores se sienten inspirados, normalmente se ponen a programa juegos" (bueno, sí, puede que lo haya cambiado un poco)

Por suerte, los artículos de HTML de la serie "deep-dive" sobre desarrollo de juegos para esta plataforma ahora ya están ampliamente disponibles. Pero en lugar de esto, prefiero ofrecer aquí una breve introducción a aquellas cosas que debemos tener en cuenta antes de ponernos a programa juegos con HTML5 y mientras estamos trabajando con ellos.

¿Qué puedes aprender en este artículo? Voy a hablar de los entornos de desarrollo de juegos para HTML5, cómo podemos llegar a mucha más gente dando soporte a smartphones y tabletas, cómo podemos avanzar en el control del estado del juego, cómo resolver los problemas de rendimiento y cómo sacar el máximo provecho a esta plataforma de juegos que es tu navegador.

Así que sin más preámbulo, aquí van las 5 buenas prácticas imprescindibles para hacer juegos con HTML5, ¡en acción! (esto de "en acción" es para añadirle algo más de dramatismo).

Buena práctica 1: utilizar un entorno

Escribir juegos sencillitos en HTML5 es fácil, pero si queremos avanzar un poco, tenemos que hacer ciertas cosas que nos aseguren que el juego funcionará correctamente.

Por ejemplo, cuando utilizamos muchas imágenes, efectos de sonido y otros recursos, el navegador puede estar un buen rato descargándolos desde el servidor web. Si no tienes en cuenta esto, te puedes llevar una sorpresa a la hora de programar el juego, porque los archivos de imagen y sonido se cargan de forma asíncrona, el código Javascript empieza a ejecutarse antes de que se hayan descargado todos los recursos. Esto suele dar como resultado un efecto "popping", (las imágenes aparecen como recuadros vacíos) y los efectos de sonido no funcionan como debieran. Una buena forma de resolver este efecto consiste en crear una rutina de precarga que retrase la ejecución del script hasta que todos los archivos ya estén descargados.

Otro problema que seguramente vas a tener es que en cada máquina, o incluso en cada navegador, el mismo juego funciona a una velocidad distinta. Aunque es cierto que aquí apenas podemos hacer nada, sin embargo podemos asegurarnos de que las animaciones y las velocidades de movimiento son independientes de la tasa de frames por segundo a la cual se ejecuta el propio juego.

Sin duda, existe UN MONTÓN de código de base que tenemos que meter dentro del juego para que funcione bien. Pero no te preocupes: no vas a tener que escribirlo tú mismo. Hay toda una familia de entornos que te permiten centrarte en la lógica del negocio sin tener que ocuparte de todas estas pequeñas (o grandes) cosas que se necesitan para que el juego funcione de manera fluida.

El único inconveniente que tiene utilizar un entorno es que hay muchos donde elegir. Algunos marcos de trabajo como ImpactJS por ejemplo, están pensados para ayudar a resolver prácticamente todos los aspectos del proceso de desarrollo de los juegos, mientras que otros como EaselJS se orientan sobre todo a la parte gráfica del desarrollo. Al final, es tu decisión el optar por aquel entorno con el que te sientas más cómodo. Puede que esto parezca una cosa sin importancia, pero en el mundo de Javascript, la elección de un entorno suele implicar a su vez tener que adaptarse a un estilo concreto de programación.

ig.module(
'monster'
)
.requires(
'impact.game',
)
.defines(function(){

Monster = ig.Entity.extend({
eyes: 42
});

});

Un buen ejemplo de esto que digo es ImpactJS, que no solo nos proporciona abstracciones para mostrar gráficos o reproducir efectos de sonido, sino que incorpora su propio modelo de objeto y herencia, tal y como se ve en el código anterior.


Ascended Arcade ha publicado tres juegos en tres meses utilizando el entorno ImpactJS.

Aunque actualmente hay muchos juegos en HTML5 que se basan en alguno de los marcos de trabajo, muchos desarrolladores siguen dándole vueltas a la posibilidad de hacerlo todo ellos mismos. Si bien puede considerarse como una excelente ocasión para aprender, si quieres terminar tus programas en un plazo razonable, sin duda la mejor manera de hacerlo es utilizando un entorno. Como ejemplo valga este excelente trabajo de Ascended Arcade que ha conseguido publicar tres excelentes (y reconocidos) juegos en solo tres meses, con la ayuda del marco ImpactJS.

Buena práctica 2: ten en cuenta los dispositivos de pantalla pequeña y táctiles

Posiblemente uno de los argumentos de venta más potentes de HTML5 es que funciona en PCs de sobremesa, portátiles, tabletas e incluso smartphones (si aún no has visto IE9 funcionando en un Windows Phone 7 Mango, echa un vistazo a este vídeo).

Esta capacidad multiplataforma (¡que piensen ya en esta palabra en el diccionario de la RAE, por favor!) tan exclusiva es intrínseca a HTML5 y por lo general requiere muy poco trabajo de adaptación por parte del desarrollador. No obstante, hay un par de cosas que tenemos que tener presentes…

Ante todo y sobre todo: los tamaños de pantalla varían enormemente entre los distintos tipos de dispositivos, igual que las resoluciones y los formatos de presentación. Si queremos que nuestros juegos en HTML5 funcionen bien también en dispositivos móviles, tenemos que asegurarnos de que soportan múltiples resoluciones o que no superan el tamaño de ventana de las pantallas WVGA (800x480 pixels).

Aparte, puesto que la mayoría de los dispositivos móviles tienen una pantalla demasiado pequeña para poder ver toda la página web a la vez, muchas veces ofrecen sistemas muy sofisticados de zoom y movimiento de la pantalla que pueden ser contraproducentes cuando se ejecutan juegos. Se pueden desactivar estas funciones por programa utilizando la etiqueta de metadatos "viewport". El siguiente bloque de código hace que el viewport de tus juegos ocupe toda la superficie horizontal disponible en pantalla. Configurando el parámetro "user-scaleable" con el valor "no", le decimos al navegador del móvil que desactive la opción de zoom, que suele dar muchos problemas con los controles de juego basados en el movimiento de los dedos por la pantalla.

<meta name="Viewport"
content="width=device-width; user-scaleable=no; initial-scale=1.0" />

Cuando hayamos comprobado que el juego se visualiza bien en dispositivos de pantalla pequeña, pensemos un poco en la introducción de datos. La mayoría de los dispositivos de tipo táctil disponen de un teclado virtual, pero tienden a ocupar una superficie bastante grande de la pantalla, lo que hace que sea una alternativa poco útil a la hora de controlar los personajes y figuras de los juegos. Si una entrada basada estrictamente en la interfaz táctil es algo irrenunciable para tu juego, tendrás que desarrollar un teclado virtual reducido que contenga únicamente los botones necesarios para tu juego (por ejemplo las flechas de dirección). Sin embargo, lo mejor es ser algo más creativo y preparar otras alternativas para controlar el juego que no requieran añadir más elementos en pantalla. Un buen ejemplo de esto es el juego Spy Chase, donde se conduce un coche con un dedo (algo que no deberíamos intentar en la vida real).

Buena práctica 3: guardar automáticamente el avance del jugador

Con funcionalidades como el anclado de sitios web a la barra de tareas, los navegadores intentan dar a las aplicaciones web el mismo estatus que tienen ya las aplicaciones normales de escritorio. De todas formas, la idea de sitios web funcionando como aplicaciones es relativamente novedosa, como también lo es la noción de páginas web que guardan el estado del lado del cliente. Te lo piensas dos veces antes de cerrar una instancia de Microsoft Word, pero seguramente no tienes tantas precauciones cuando abres una página web. La mayoría de las veces esto no es un problema, ya que casi todas las páginas web o bien no tienen en cuenta el estado, o mantienen la información de registro en el servidor.

Los juegos para navegador web, no obstante, son un caso ligeramente distinto. Puesto que el código JavaScript se ejecuta en el lado del cliente, los juegos para HTML5 normalmente mantienen la información de estado dentro de una memoria temporal (o sea, la RAM). Cierras la ventana del navegador y esa puntuación que tanto sudor te ha costado ganarte se pierde para siempre.

Ahora podrás discutirme que una persona sensata tendrá cuidado de no cerrar el juego en el que ha estado jugando durante ocho horas, pero… los accidentes también ocurren, sobre todo cuando tienes en pantalla varias pestañas o cuando las baterías se vuelven locas.

En resumen: a la hora de programar juegos para HTML5, una buena práctica indispensable consiste en ir guardando el nivel de progreso del jugador cada cierto tiempo y dejar que los jugadores puedan recuperar el juego en el mismo lugar cuando vuelvan a abrir la página web que han cerrado anteriormente.

Ahora bien ¿dónde tenemos que guardar el estado del juego? En el pasado, el lugar obvio era una base de datos en el lado del servidor, o bien una cookie en el lado del cliente. Ninguna de estas opciones es demasiado atractiva. Si seguimos la alternativa del lado del servidor, deben ejecutarse peticiones HTTP siempre que se necesite guardar o recuperar la información almacenada. La estrategia de la cookie nos limita mucho el espacio de trabajo y la longevidad de la propia cookie depende en gran medida de la configuración del navegador.

Una solución mucho más práctica consiste en utilizar el almacenamiento DOM de HTML5. El almacenamiento DOM nos permite guardar varios megas de datos por sitio web mediante una interfaz que se asemeja mucho a las utilizadas para guardar pares de clave-valor (o al objeto expand de Javascript). Es muy cómoda, pero en el contexto de los juegos para HTML5, seguramente nos vendría muy bien poder guardar estructuras de datos complejas, algo que no soporta el almacenamiento DOM de forma nativa.

Por suerte en este caso, las actuales implementaciones de Javascript disponen de mecanismos integrados que nos permiten serializar objetos dentro de una notación compacta conocida JSON. Con esta técnica, el almacenamiento de DOM se puede utilizar también para guardar cualquier información que queramos. Las dos siguientes funciones muestran cómo se puede guardar el estado de un juego y recuperarlo después utilizando el almacenamiento de DOM y las funciones JSON integradas dentro de ECMAScript5:

function saveState(state) {
   window.localStorage.setItem("gameState", JSON.stringify(state));
}

function restoreState() {
   var state = window.localStorage.getItem("gameState");
   if (state) {
      return JSON.parse(state);
   } else {
      return null;
   }
}

Buena práctica 4: Utiliza un perfilador

Uno de los retos más difíciles a la hora de desarrollar un juego es el poder mantener tasas de frames por segundo elevadas a medida que vamos añadiéndole más elementos y funciones.

La buena noticia es que los navegadores en general ahora son bastante más rápidos que hace un par de años, y los juegos preparados para HTML5 que operan a una tasa constante de 60 fps son ya una realidad.

No ha sido fácil. EN el caso de Internet Explorer 9, esto supone haber tenido que reescribir todo un nuevo motor de Javascript capaz de utilizar varios cores de la CPU y un pipeline de presentación totalmente acelerado por hardware basado en Direct2D. Dicho en otras palabras: si te has gastado un buen dinerito en tu equipo para jugar con él, Internet Explorer dará buena cuenta de ello.


El perfilador de Javascript integrado en Internet Explorer 9 nos ayuda a detector cuellos de botella en el rendimiento de un juego.

En el caso de los juegos más sencillos, esto supone que ya no tendremos que ocuparnos del tema del rendimiento. Pero dado que HTML5 es independiente de la plataforma, en teoría podemos desarrollar para toda una gama de dispositivos y navegadores muy variados, que puede que no sean tan rápidos como nos gustaría. Aunque estemos pensando en correr nuestro juego únicamente en PCs de gama alta (algo que habíamos quedado que no íbamos a hacer, ¿te acuerdas?), el rendimiento puede seguir siendo un aspecto problemático.

Si quieres que tu juego funcione a 60 frames por segundo, no dispones más que de 16 milisegundos para restituir cualquier frame individual. En el tiempo que tardamos en abrir y cerrar los ojos, tenemos que dibujar en pantalla un mínimo de 6 frames completos. Realmente parece una tarea agotadora… y para cualquier juego medianamente complicado, esto es así.

Pero por suerte tenemos herramientas que nos pueden ayudar. En Internet Explorer 9 (o 10 si es el caso), pulsando la tecla F12 se nos abren las herramientas de desarrollo. Selecciona la pestaña "Profiler" y pulsa luego "Start profiling" para empezar con el perfilado.

Ahora, muévete hasta el punto donde crees que se puede mejorar el rendimiento, déjale al perfilador un margen de unos 30 segundos para que obtenga sus datos, y luego pulsa en "Stop profiling." Te mostrará un resumen del tiempo de ejecución acumulada que han consumido cada una de las funciones del juego. La mayoría de las veces verás que hay unas cuantas funciones que se llevan la mayor parte del tiempo de ejecución general. Al optimizar esas funciones seguramente tendremos los mejores resultados y, cuando analices el código, aparecerán casi de inmediato las subrutinas que ralentizan la ejecución.

Pero no te fíes de tu instinto demasiado a ciegas: el código que parece lento puede que se ejecute mucho más rápidamente en los motores de Javascript actuales. La mejor estrategia para la optimización consiste en ejecutar el perfilador a menudo y medir en todos los casos el resultado de los cambios que hacemos, para detectar si esos cambios provocan el impacto positivo en el rendimiento que esperamos.


Juegos para redes sociales: Warimals se basa en HTML5 y nos permite jugar con nuestros amigos en Facebook.

Buena práctica 5: ¡se original!

Poder programar juegos que funcionen de manera nativa en tu ordenador es una pasada, pero aún lo es más el que HTML5 nos permite programar juegos que FUNCIONAN EN TU NAVEGADOR. HTML5 es interesante no solo desde el punto de vista tecnológico, sino que además el navegador web es una plataforma ideal para los juegos.

Piénsalo… los navegadores están en muchos dispositivos diferentes, están conectados (prácticamente) siempre y son el medio que utiliza todo el mundo para conectarse con los demás con el correo, el chat y las redes sociales. Como desarrollador de juegos para la web, puedes crear juegos divertidos y que hagan posible que jueguen juntos personas de todo el mundo.

Si eres nuevo en esto de desarrollar juegos para HTML5, seguramente te tentará la idea de escribir réplicas de juegos que ya disfrutas sin conexión. No hay nada de malo en esto. Pero si quieres que tu juego se pueda utilizar dentro de una "aplicación de comunicación", lo mejor es que te pongas a imaginar ideas nuevas y realmente originales para tus juegos. Un ejemplo interesante de esto es el juego Warimals, uno de los primeros juegos para Facebook preparado para HTML5. En Warimals podemos jugar a ser perros o gatos, y podemos invitar a nuestros amigos de Facebook a jugar con nosotros ¿a que mola?

En resumen…

Gracias al excelente trabajo de los creadores de entornos de trabajo y los pioneros en Javascript, HTML5 se ha convertido ya en una plataforma Madura para la programación de juegos. Es una gran noticia, porque la web es el entorno de ejecución más universal para aplicaciones de todo tipo. Con las herramientas adecuadas (muchas de las cuales ya vienen cómodamente integradas en Internet Explorer 9 y 10 o se pueden descargar de forma gratuita) y el marco de trabajo adecuado, la experiencia de desarrollo de juegos para HTML5 puede ser todo un placer y muy estimulante, sobre todo para crear experiencias conectadas y con ideas interesantes y originales.

Herramientas que te recomiendo para empezar:

Kai Jäger

Academic Developer Evangelist de Microsoft en Alemania.

Manual