Creando Roll It

Roll It es un Experimento de Chrome que reinventa un juego clásico de paseo marítimo con solo el navegador en tu teléfono y computadora. El navegador de tu teléfono te permite apuntar y hacer rodar la bola con un movimiento de muñeca, mientras que el navegador de tu computadora renderiza los gráficos en tiempo real del callejón de Roll It con WebGL y Canvas. Los dos dispositivos se comunican a través de Websockets. No hay aplicaciones. No hay descargas. No hay tokens. Solo necesitas un navegador moderno.

Con la dirección de Google Creative Lab, Legwork desarrolló la experiencia del usuario, las interfaces y el entorno de juego, y luego se asoció con el socio de desarrollo, Mode Set, para crear Roll It. Durante el proyecto, hubo una serie de desafíos únicos. En este artículo, se describen algunas de las técnicas que usamos, los trucos que descubrimos y las lecciones que aprendimos mientras llevamos a cabo Roll It.

Flujo de trabajo en 3D

Una de las dificultades al principio fue encontrar la mejor manera de llevar los modelos 3D de nuestro software a un formato de archivo listo para la Web. Después de crear los recursos en Cinema 4D, los modelos se simplificaron y se convirtieron en mallas de polígonos bajos. A cada malla se le asignaron ciertas etiquetas de selección de polígonos para diferenciar las partes del objeto para aplicarles color y textura. Luego, pudimos exportar como un archivo Collada 1.5 (.dae) y, luego, importarlo a Blender, un programa 3D de código abierto, para crear archivos compatibles con three.js. Una vez que nos aseguramos de que nuestros modelos se importaron correctamente, exportamos la malla como un archivo JSON y la iluminación se aplicó con código. A continuación, se muestra una descripción más detallada de los pasos que seguimos:

Modela el objeto en C4D. Asegúrate de que las normales de la malla estén orientadas hacia afuera.
Modela el objeto en C4D. Asegúrate de que las normales de la malla estén orientadas hacia afuera.
Con la herramienta de selección de polígonos, crea etiquetas de selección de las áreas específicas a las que deseas aplicarles texturas. Aplica materiales a cada una de las etiquetas de selección.
Con la herramienta de selección de polígonos, crea etiquetas de selección de las áreas específicas a las que deseas aplicar texturas. Aplica materiales a cada una de las etiquetas de selección.
Exporta tu malla como un archivo.dae de COLLADA 1 .5.
Exporta tu malla como un archivo.dae de COLLADA 1 .5.
Asegúrate de que la opción "Exportar geometría 2D" esté marcada. Por lo general, la exportación de triángulos es más compatible con los entornos 3D en el código, pero tiene el inconveniente de duplicar el recuento de polígonos. Cuanto mayor sea el recuento de polígonos, más exigente será el modelo para el procesador de la computadora. Por lo tanto, deja esta opción marcada si observas un rendimiento lento.
Asegúrate de que la opción "Exportar geometría 2D" esté marcada. Por lo general, la exportación de triángulos es más compatible con los entornos 3D en el código, pero tiene el inconveniente de duplicar el recuento de polígonos. Cuanto mayor sea el recuento de polígonos, más exigente será el modelo para el procesador de la computadora. Por lo tanto, deja esta opción marcada si observas un rendimiento lento.
Importa el archivo Collada a Blender.
Importa el archivo Collada en Blender.
Una vez que lo hagas, verás que tus materiales y etiquetas de selección también se transfirieron.
Una vez que se importen a Blender, verás que los materiales y las etiquetas de selección también se transfirieron.
Selecciona el objeto y ajusta los materiales según tus preferencias.
Selecciona el objeto y ajusta los materiales según tus preferencias.
Exporta el archivo como un archivo three.js.
Exporta el archivo como un archivo three.js para la compatibilidad con WebGL.

Cómo escribir el código

Roll It se desarrolló con bibliotecas de código abierto y se ejecuta de forma nativa en navegadores modernos. Con tecnologías como WebGL y WebSockets, la Web se acerca a las experiencias multimedia y de juegos de calidad de consola. La facilidad y comodidad con las que los desarrolladores pueden crear estas experiencias ha avanzado a pasos agigantados a medida que se han puesto a disposición herramientas más modernas para el desarrollo de HTML.

El entorno de desarrollo

La mayor parte del código original de Roll It se escribió con CoffeeScript, un lenguaje limpio y conciso que se transpila a JavaScript bien formado y linteado. CoffeeScript se destaca en el desarrollo de OOP con su excelente modelo de herencia y un manejo de alcance más limpio. El CSS se escribió con el framework SASS, que le brinda al desarrollador una serie de herramientas excelentes para mejorar y administrar los diseños de página de un proyecto. Agregar estos sistemas al proceso de compilación lleva un poco de tiempo de configuración, pero la recompensa vale la pena, especialmente para un proyecto más grande como Roll It. Configuramos un servidor Ruby on Rails para compilar automáticamente nuestros recursos durante el desarrollo, de modo que todos estos pasos de compilación se volvieron transparentes.

Además de crear un entorno de codificación optimizado y cómodo, optimizamos manualmente los recursos para minimizar las solicitudes y cargar el sitio más rápido. Ejecutamos cada imagen a través de un par de programas de compresión: ImageOptim y ImageAlpha. Cada programa optimiza las imágenes a su manera, sin pérdida y con pérdida, respectivamente. Con la combinación correcta de parámetros de configuración, pueden reducir significativamente el tamaño del archivo de una imagen. Esto no solo ahorra ancho de banda cuando se cargan imágenes externas, sino que, una vez optimizadas, tus imágenes se traducirán en cadenas con codificación base64 mucho más pequeñas para la incorporación intercalada en HTML, CSS y JavaScript. En cuanto al tema de la codificación base64, también incorporamos nuestros archivos de fuentes WOFF y SVG de Open Sans directamente en el CSS con esta técnica, lo que generó aún menos solicitudes totales.

La escena 3D habilitada para la física

THREE.js es la biblioteca de JavaScript 3D omnipresente para la Web. Combina matemáticas en 3D de bajo nivel y optimizaciones de WebGL basadas en hardware que permiten a los simples mortales crear fácilmente escenas interactivas en 3D bien iluminadas y hermosas sin tener que escribir sombreadores personalizados ni realizar transformaciones de matrices manuales. Physijs es un wrapper específico de THREE.js para una biblioteca de física C++ popular que se tradujo a JavaScript. Aprovechamos esta biblioteca para simular la bola que rueda, salta y rebota hacia su destino en 3D.

Desde el principio, nos propusimos no solo hacer que la experiencia física de hacer rodar la pelota se sintiera realista, sino también asegurarnos de que los objetos del juego se sintieran reales. Esto requirió muchas iteraciones para ajustar la gravedad general de la escena de Physijs, la velocidad de la bola a medida que rueda desde el lanzamiento del jugador, la pendiente del salto de la pista y las propiedades de fricción y restitución (elasticidad) de la bola y los materiales de la pista. La combinación de más gravedad y más velocidad generó una experiencia de juego más realista.

Suaviza el resultado

La mayoría de las combinaciones modernas de navegador y tarjeta de video deberían aprovechar el antialiasing nativo basado en hardware en el entorno de WebGL, pero algunas no funcionan bien. En caso de que el suavizado no funcione de forma nativa, los bordes duros y contrastantes de la escena de THREE.js serán irregulares y feos (al menos para nuestros ojos exigentes).

Por suerte, hay una solución: a través de un fragmento de código, podemos detectar si la plataforma admitirá de forma nativa el suavizado de bordes. Si es así, podemos continuar. Si no, hay una serie de sombreadores de procesamiento posterior que vienen con THREE.js que pueden ayudarnos. Es decir, el filtro de suavizado FXAA. Cuando se vuelve a dibujar la escena renderizada en cada fotograma con este sombreador, por lo general, se obtiene un aspecto mucho más suave para las líneas y los bordes. Consulta la demostración a continuación:

// Check for native platform antialias support via the THREE renderer
// from: http://codeflow.org/entries/2013/feb/22/how-to-write-portable-webgl/#antialiasing
var nativeAntialiasSupport = (renderer.context.getParameter(renderer.context.SAMPLES) == 0) ? false : true;

Controles de juegos basados en acelerómetro

Gran parte de la magia de Roll It proviene del gesto de hacer rodar la pelota que el jugador realiza con un teléfono. Los dispositivos móviles tienen acceso al acelerómetro dentro del navegador desde hace tiempo, pero como industria, recién estamos comenzando a explorar el reconocimiento de gestos basado en el movimiento en la Web. Los datos que proporciona el acelerómetro del teléfono nos limitan un poco, pero con un poco de creatividad podemos crear experiencias nuevas y geniales.

Detección de giro: El gesto principal de "giro" comienza con el seguimiento de las 10 actualizaciones más recientes del acelerómetro que provienen del evento deviceorientation de la ventana. Cuando restamos el valor de inclinación anterior del valor de inclinación actual, almacenamos el delta de ángulo entre los eventos. Luego, si sumamos constantemente los últimos diez deltas de ángulo, podemos detectar la rotación continua a medida que el teléfono se mueve en el espacio. Cuando el teléfono supera un umbral de cambio de ángulo de barrido, activamos un giro. Luego, cuando encontramos el delta de inclinación más grande en ese barrido, podemos estimar una velocidad para la pelota. En Roll It, esta velocidad se normaliza con marcas de tiempo que adjuntamos a cada actualización del acelerómetro. Esto ayuda a suavizar la velocidad variable con la que las actualizaciones del acelerómetro se transmiten al navegador en diferentes dispositivos.

Comunicación de WebSockets

Una vez que el jugador hace rodar la pelota con el teléfono, se envía un mensaje del teléfono a la laptop para que lance la pelota. Este mensaje de “rollo” se envía a través de un objeto de datos JSON mediante una conexión WebSocket entre las dos máquinas. Los datos JSON son pequeños y consisten principalmente en un tipo de mensaje, una velocidad de lanzamiento y una dirección de objetivo.

{
  "type": "device:ball-thrown",
  "speed": 0.5,
  "aim": 0.1
}

Toda la comunicación entre la laptop y el teléfono se realiza a través de pequeños mensajes JSON como este. Cada vez que el juego actualiza su estado en la computadora de escritorio o el usuario inclina o presiona un botón en el teléfono, se transmite un mensaje WebSocket entre las máquinas. Para que esta comunicación sea simple y fácil de administrar, los mensajes de WebSockets se transmiten con un solo punto de salida desde cualquier navegador. Por el contrario, hay un solo punto de entrada en el navegador receptor, con un objeto WebSocket que controla todos los mensajes entrantes y salientes en ambos extremos. Cuando se recibe un mensaje de WebSocket, los datos JSON se vuelven a transmitir dentro de la app de JavaScript con el método trigger() de jQuery. En este punto, los datos entrantes se comportan como cualquier otro evento del DOM personalizado y pueden ser detectados y procesados por cualquier otro objeto de la aplicación.

var websocket = new WebSocket(serverIPAddress);

// rebroadcast incoming WebSocket messages with a global event via jQuery
websocket.onmessage = function(e) {
  if (e.data) {
    var obj = JSON.parse(e.data);
    $(document).trigger(data.type, obj);
  }
};

// broadcast outgoing WebSocket messages by passing in a native .js object
var broadcast = function(obj) {
  websocket.send(JSON.stringify(obj));
};

Los servidores de WebSocket de Roll It se crean sobre la marcha cuando se sincronizan dos dispositivos con un código de juego. El backend de Roll It se compiló en la plataforma de Google Compute Engine y App Engine con Go.

Pantallas de menú con inclinación

Además de los mensajes de WebSocket basados en eventos que se usan durante el juego, los menús de Roll It se controlan inclinando el teléfono y presionando un botón para confirmar una selección. Esto requiere una transmisión más coherente de datos de inclinación desde el teléfono a la laptop. Para reducir el ancho de banda y evitar el envío de actualizaciones innecesarias, estos mensajes solo se envían si la inclinación del dispositivo cambió en más de un par de grados. No tiene sentido enviar una transmisión de datos de inclinación si el teléfono está sobre una mesa. La velocidad de transmisión también se limita: no se envían más de 15 mensajes de WebSocket por segundo en Roll It, incluso si el dispositivo se inclina de forma activa.

Una vez que se detectan los valores de inclinación en la computadora, se interpolan con el tiempo mediante requestAnimationFrame para mantener una sensación fluida. El resultado final es un menú rotativo y una bola que rueda para indicar la selección del usuario. A medida que el teléfono envía datos de inclinación, estos elementos DOM se actualizan en tiempo real mediante el recálculo de una transformación CSS dentro del bucle requestAnimationFrame. El contenedor del menú simplemente rota, pero la bola parece rodar por el suelo. Para lograr este efecto, implementamos algunos conceptos básicos de trigonometría para relacionar la coordenada x de las bolas con su rotación. La ecuación simple es: rotaciones = x / (diámetro × π).

Conclusión

Roll It es un signo de los tiempos. Entre los proyectos de código abierto que impulsaron su desarrollo, la potencia de procesamiento de los dispositivos que tenemos en nuestros escritorios y en nuestros bolsillos, y el estado de la Web como plataforma, es un momento realmente emocionante y transformador para conectarse en la Web abierta. Hace apenas unos años, gran parte de esta tecnología solo existía en sistemas propietarios, no disponibles para su uso y distribución gratuitos. Hoy en día, las experiencias complejas se pueden lograr con menos trabajo y más imaginación a medida que creamos y compartimos nuevas piezas del rompecabezas todos los días. ¿Qué estás esperando? Crea algo increíble y compártelo con el mundo.

Logotipo de Roll it