Creando Roll It

Roll It es un experimento de Chrome que reinventa un juego clásico de paseo marítimo usando solo el navegador de tu teléfono y computadora. El navegador del teléfono te permite apuntar y hacer rodar la pelota con un giro de muñeca, mientras que el navegador de la computadora procesa los gráficos en tiempo real de la calle Roll It con WebGL y Canvas. Los dos dispositivos se comunican a través de Websockets. No hay apps. No más descargas. No hay tokens. Solo necesitas un navegador actualizado.

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 desarrollar Roll It. A lo largo del proyecto, hubo una serie de desafíos únicos. En este artículo, se explican algunas de las técnicas que utilizamos, los trucos que descubrimos y las lecciones que aprendimos para dar vida a Roll It.

Flujo de trabajo en 3D

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

Modelar el objeto dentro de C4D Asegúrate de que las normales de la malla queden hacia afuera.
Modela el objeto dentro de C4D. Asegúrate de que las normales de la malla queden hacia afuera.
Con la herramienta de selección de polígonos, crea etiquetas de selección de las áreas específicas a las que desees aplicar textura. 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 con las que quieras aplicar textura. Aplica materiales a cada una de las etiquetas de selección.
Exporta tu malla como un archivo COLLADA 1.5 .dae.
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 entornos 3D en el lado del código, pero tiene la desventaja de duplicar el recuento de polígonos. Cuanto mayor sea el número de polígonos, mayor será la imposición del modelo para el procesador de la computadora. Por lo tanto, deja marcada esta opción si observas un rendimiento lento.
Asegúrate de que esté marcada la opción "Exportar geometría 2D". Por lo general, la exportación de triángulos es más compatible con entornos 3D en el lado del código, pero tiene la desventaja de duplicar el recuento de polígonos. Cuanto mayor sea el número de polígonos, mayor será la imposición del modelo para el procesador de la computadora. Por lo tanto, déjala marcada si observas un rendimiento lento.
Importa el archivo de Collada a Blender.
Importa el archivo de Collada a Blender.
Una vez que lo hayas importado a la licuadora, verás que también se trasladaron los materiales y las etiquetas de selección.
Después de importarla a la licuadora, verás que también se trasladaron los materiales y las etiquetas de selección.
Selecciona el objeto y ajusta los materiales del objeto según tus preferencias.
Selecciona tu objeto y ajusta sus materiales según tus preferencias.
Exporta el archivo como archivo{3}.js
Exporta el archivo como archivo 3.js para compatibilidad con webGL.

Escribe el código

Roll It se desarrolló con bibliotecas de código abierto y se ejecuta de forma nativa en los navegadores modernos. Con tecnologías como WebGL y WebSockets, la Web se está acercando a las experiencias multimedia y de videojuegos de calidad de consola. La facilidad y el confort con que los desarrolladores pueden crear estas experiencias ha ido avanzando a medida que se encuentran disponibles 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 transcompila a JavaScript con lint y buen formato. CoffeeScript se destaca por el desarrollo OOP gracias a su gran modelo de herencia y un manejo más claro del alcance. El CSS se escribió con el marco de trabajo SASS, que brinda al desarrollador varias herramientas excelentes para mejorar y administrar las hojas de estilo de un proyecto. Agregar estos sistemas al proceso de compilación lleva un poco de tiempo, pero definitivamente vale la pena, especialmente para un proyecto más grande como Roll It. Configuramos un servidor de Ruby on Rails para que compile 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 programación cómodo y optimizado, 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 e ImageAlpha. Cada programa optimiza las imágenes a su manera: con y sin pérdida, respectivamente. Con la combinación adecuada de parámetros de configuración, pueden reducir significativamente el tamaño de archivo de una imagen. Esto no solo ahorra ancho de banda cuando se cargan imágenes externas, sino que, una vez optimizadas, se traducen las imágenes en cadenas codificadas en base64 mucho más pequeñas para la incorporación intercalada en HTML, CSS y JavaScript. En el tema de la codificación en base64, también incorporamos nuestros archivos de fuentes WOFF y SVG Open Sans directamente en el CSS con esta técnica, lo que dio como resultado una menor cantidad de solicitudes en total.

La escena 3D habilitada para la física

THREE.js es la biblioteca 3D de JavaScript para la Web. Incluye matemáticas de bajo nivel en 3D y optimizaciones de WebGL basadas en hardware que permiten a los mortales crear fácilmente escenas interactivas en 3D atractivas y bien iluminadas, 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 de C++ popular que se tradujo a JavaScript. Aprovechamos esta biblioteca para simular en 3D cómo se mueve la pelota, salta y rebota hacia su destino.

Desde el principio, nos propusimos no solo hacer que la experiencia física de hacer rodar la pelota fuera realista, sino también asegurarnos de que los objetos del juego fueran reales. Esto requirió muchas iteraciones de ajuste de la gravedad general de la escena de Physijs, la velocidad de la pelota cuando lanza desde el lanzamiento del jugador, la pendiente del salto del carril y las propiedades de fricción y restitución (restitución) de la pelota y los materiales del carril. La combinación de más gravedad y mayor velocidad dio como resultado una experiencia de juego más realista.

Suavizar

La mayoría de las combinaciones modernas de navegador y tarjetas de video deberían aprovechar el suavizado de contorno basado en hardware nativo en el entorno de WebGL, pero algunas no funcionarán bien. En el caso de que el suavizado de contorno no funcione de forma nativa, cualquier borde rígido y contrastado en la escena de THREE.js será dentado y feo (al menos para nuestros ojos más exigentes).

Afortunadamente, 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 contorno. Si es así, ya estamos listos. Si no es así, hay una serie de sombreadores de procesamiento posterior que vienen con THREE.js que pueden ayudarnos. es decir, el filtro de suavizado de contorno de FXAA. Cuando se vuelve a dibujar la escena renderizada cada fotograma con este sombreador, por lo general, obtenemos una apariencia mucho más suave de nuestras líneas y bordes. Observa la siguiente demostració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 juego basados en el acelerómetro

Gran parte de su magia radica en el gesto de lanzar la pelota que el jugador hace con un teléfono. Desde hace ya un tiempo, los dispositivos móviles han tenido acceso al acelerómetro dentro del navegador, pero como industria 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 de alguna manera, pero, con un poco de creatividad, podemos ofrecer experiencias nuevas geniales.

La detección de su gesto principal de "rollo" comienza con el seguimiento de las 10 actualizaciones más recientes del acelerómetro que provienen del evento deviceorientation de la ventana. Si se resta el valor de inclinación anterior al valor de inclinación actual, se almacena el delta del ángulo entre los eventos. Luego, si sumamos constantemente los últimos diez deltas de ángulos, podemos detectar la rotación continua a medida que el teléfono se mueve por el espacio. Cuando el teléfono pasa un umbral de cambio de ángulo de barrido, se activa un giro. Luego, si encontramos el delta de inclinación individual más grande en ese barrido, podemos estimar la velocidad de la bola. En Roll It, esta velocidad se normaliza mediante 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 girar la pelota con el teléfono, se envía un mensaje del teléfono a la laptop en el que se le indica que lance la pelota. Este mensaje de “rollo” se envía a través de un objeto de datos JSON a través de una conexión de WebSocket entre las dos máquinas. Los datos de JSON son pequeños y consisten principalmente de un tipo de mensaje, una velocidad de lanzamiento y una dirección del objetivo.

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

Toda la comunicación entre la laptop y el teléfono ocurre 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 del teléfono, se transmite un mensaje de WebSocket entre las máquinas. Para mantener esta comunicación simple y fácil de administrar, los mensajes de WebSockets se transmiten con un único punto de salida desde cualquiera de los navegadores. En cambio, hay un único 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 aplicación de JavaScript con el método trigger() de jQuery. En este punto, los datos entrantes se comportan como cualquier otro evento de DOM personalizado, y cualquier otro objeto de la aplicación puede tomarlos y procesarlos.

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 se crean sobre la marcha cuando dos dispositivos se sincronizan con un código de juego. El backend de Roll It se compiló en las plataformas de Google Compute Engine y App Engine mediante Go.

Inclinación de pantallas de menú

Más allá de los mensajes de WebSocket controlados por 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 un flujo más coherente de datos de inclinación que se transmiten 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 se modifica en más de un par de grados. No tiene sentido enviar un flujo de datos de inclinación si el teléfono está apoyado sobre una mesa. También se limita la frecuencia de transmisión: no se envían más de 15 mensajes de WebSockets por segundo en la función Roll It, incluso si el dispositivo se está inclinando de forma activa.

Una vez que se obtienen los valores de inclinación en la computadora, se interpolan con el tiempo mediante requestAnimationFrame para lograr una sensación fluida. El resultado final es un menú giratorio y una pelota que lanza para ayudar a indicar la selección del usuario. A medida que el teléfono envía datos de inclinación, estos elementos del DOM se actualizan en tiempo real cuando se vuelve a calcular una transformación de CSS dentro del bucle requestAnimationFrame. El contenedor del menú simplemente gira, pero la pelota parece rodar por el suelo. Para lograr este efecto, implementamos una trigonometría básica para relacionar la coordenada X de las bolas con su rotación. La ecuación simple es: rotaciones = x / (diámetro * π)

Conclusión

Rollo es una señal de los tiempos. Entre los proyectos de código abierto que impulsaron su desarrollo, la potencia de procesamiento de los dispositivos en nuestros escritorios y bolsillos, y el estado de la Web como plataforma, es un momento verdaderamente emocionante y transformador para estar conectado en la Web abierta. Solo unos años atrás, gran parte de esta tecnología existía solo en sistemas propios, que no estaban disponibles para su uso y distribución libremente. Hoy en día, las experiencias complejas se pueden realizar 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? Construye algo genial y compártelo con el mundo.

Logotipo de Roll it