Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Gamepad

Agregar soporte a controlador en los juegos HTML5 con la API Gamepad

by
Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

A medida que los juegos basados en la web se vuelven más populares, uno de los mayores puntos de adherencia para los jugadores es el control de entrada. Mientras que mis primeros juegos de FPS eran puramente de ratón y basado en el teclado, ahora tengo mucho más utilizado para un controlador de consola adecuado que prefiero usarlo para todo, incluidos los juegos basados en web.

Por suerte, el HTML5 Gamepad API existe para permitir a los desarrolladores web acceso programático a los controladores de juegos. Desafortunadamente, aunque esta API ha existido durante mucho tiempo, es sólo ahora, poco a poco, moviéndose a las versiones más recientes de los navegadores de escritorio. Se languideció durante mucho tiempo en una versión de Firefox (no una versión más alta—ninguna compilacion nightly) y fue problemática en Chrome. Ahora—bien—no es perfecto, pero un poco menos problemático y realmente bastante fácil de usar.

En este artículo, voy a discutir las diversas características de la API, cómo conseguir que funcione en Firefox y Chrome, y mostrar un juego real (si es simple) y lo fácil que es agregar soporte de mando de videojuegos a ella.

Lo basico

El API Gamepad comprende las siguientes características:

  • La capacidad de escuchar eventos connect y disconnect.
  • La capacidad de reconocer múltiples mandos de juegos. (En teoría, podría conectar tantos mandos de jeugos como cuantos puertos USB tengas.)
  • La capacidad de inspeccionar estos gamepads y reconocer cuántos ejes tienen (joysticks), cuántos botones tienen (¿has jugado una consola de juegos moderna últimamente?), Y en qué estado cada uno de estos elementos individuales se encuentran.

Comencemos por discutir cómo puede detectar el soporte para un gamepad a un nivel alto.

Tanto Firefox como Chrome soportan un método en navigator, getGamepads(), que devuelve una matriz de todos los dispositivos de gamepad conectados. Podemos usar esto como un método simple para detectar si la API Gamepad está presente. Aquí está una función simple para esa comprobación:

Hasta aquí todo bien. Ahora para la parte funky. La API de Gamepad tiene soporte para eventos que detectan cuándo un gamepad está conectado y desconectado. La API de Gamepad tiene soporte para eventos que detectan cuándo un gamepad está conectado y desconectado. Normalmente, la página web esperará a que el usuario haga algo, cualquier cosa realmente, con el gamepad real. Esto significa que tenemos que proporcionar algún tipo de mensaje al usuario que les permite saber que necesitan "despertar" el soporte para el mando de juego si está conectado. Podrías decirles que toquen cualquier botón o muevan la palanca.

Para hacer las cosas aún más interesantes, este cheque en particular no parece necesario cuando se vuelve a cargar la página. Verá que una vez que haya utilizado la API de Gamepad en una página y luego la vuelva a cargar, la página reconoce este hecho y automáticamente lo considera conectado.

Pero espera—se pone mejor. Chrome no admite los eventos conectados (o desconectados) en este momento. El trabajo típico para esto (y el que se demuestra en los buenos documentacion MDN para la API) es configurar una encuesta y ver si un mando de juego "aparece" en la lista de dispositivos conectados.

¿Confuso? Comencemos con un ejemplo que sólo es compatible con Firefox:

En el ejemplo anterior, comenzamos por comprobar si el navegador admite la API del Gamepad. Si lo hace, primero actualizamos una div con instrucciones para el usuario y luego comenzamos a escuchar inmediatamente los eventos connect y disconnect.

Si ejecutas esto con Firefox y conectas tu mando de juego, deberías tener que pulsar un botón, momento en el que se dispara el evento y ya está listo.

De nuevo, sin embargo, en mis pruebas, cuando vuelvo a cargar la página, el evento connection es inmediato. Esto crea un ligero efecto de "parpadeo" que puede ser indeseable. Usted podría utilizar un intervalo para establecer las direcciones para algo como 250ms después de que el DOM ha cargado y sólo se preguntan si una conexión no se produjo en el ínterin. Decidí mantener las cosas simples para este tutorial.

Nuestro código funciona para Firefox, pero ahora vamos a agregar soporte para Chrome:

El código es un poco más complejo, pero no terriblemente. Cargue la demostración en Chrome y vea qué sucede.

Tenga en cuenta que tenemos una nueva variable global, hasGP, que usaremos como indicador general para tener un mando de juego conectado. Como antes, tenemos dos oyentes de eventos, pero ahora tenemos un nuevo intervalo configurado para comprobar si existe un mando de juego. Esta es la primera vez que ves getGamepads en acción, y lo describiremos un poco más en la siguiente sección, pero por ahora sabemos que sólo devuelve una matriz y si el primer elemento existe, podemos usarlo como Una forma de saber que un mando de juego está conectado.

Utilizamos jQuery para disparar el mismo evento que Firefox habría recibido, y luego borrar el intervalo. Tenga en cuenta que este mismo intervalo se disparará una vez en Firefox, así, que es un poco derrochador, pero honestamente, pensé que era una pérdida de tiempo añadiendo soporte adicional para probar Chrome frente a Firefox. Una pequeña llamada como esta desperdiciada en Firefox no debería importar en absoluto.

Ahora que tenemos un gamepad conectado, ¡vamos a trabajar con él!

El objeto Gamepad

Para darle una idea de cuántos años tengo - aquí está el joystick de última generación que usé para mi primer sistema de juegos.


Imagen de Wikimedia Commons.

Bonito - simple - y dolia como mucho después de una hora de jugar. Consolas modernas tienen mandos de juegos mucho más complejos. Considere el controlador PS4:

Imagen de Wikimedia Commons.

Este controlador tiene dos palos, una almohadilla direccional, cuatro botones principales, cuatro más en la parte posterior, un botón Share y Options, un botón PS, control táctil, un altavoz y una luz. También probablemente tiene un condensador de flujo y un fregadero de la cocina.

Afortunadamente, tenemos acceso a esta bestia a través del objeto Gamepad. Las propiedades incluyen:

  • id: Este es el nombre del controlador. No esperes un nombre amigable aqui. Mi DualShock 4 fue reportado como 54c-5c4-Wireless Controller en Firefox, mientras que Chrome llamó al mismo controlador Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 05c4).
  • index: Dado que la API de Gamepad admite varios controladores, éste le permite determinar qué controlador numerado es. Podría ser usado para identificar al jugador uno, dos, y así sucesivamente.
  • mapping: Mapping no es algo que vamos a cubrir aquí, pero esencialmente esto es algo que el navegador puede hacer para ayudar a asignar su controlador particular a una configuración de controlador "estándar". Si has jugado varias consolas, sabes que tienen algunas similitudes en términos de control, y la API intenta "aplastar" tu controlador en un estándar. No tiene que preocuparse por esto por ahora, pero si desea obtener más detalles, consulte la sección mapping de los documentos de la API.
  • connected: Un booleano que indica si el controlador sigue conectado.
  • buttons: una matriz de valores de botón. Cada botón es una instancia de GamepadButton. Tenga en cuenta que el objeto GamepadButton admite tanto una propiedad booleana simple (pressed) como una propiedad value para botones analógicos.
  • axes: Una matriz de valores que representan las diferentes palancas en el mando de juegos. Dado un gamepad con tres palos, tendrás una matriz de seis elementos, donde cada palo está representado por dos valores de matriz. El primero del par representa X, o movimiento de izquierda / derecha, mientras que el segundo representa Y, movimiento de arriba / abajo. En todos los casos el valor oscilará entre -1 y 1: para los valores izquierdo / derecho, -1 es izquierdo y 1 es derecho; Para los valores arriba / abajo, -1 es arriba y 1 es abajo. Según la API, la matriz se clasifica de acuerdo con la "importancia", por lo que en teoría, puede centrarse en los axes[0] y los axes[1] para la mayoría de las necesidades de juego. Para hacer las cosas más interesantes, utilizando mi DualShock 4, Firefox informó tres ejes (que tiene sentido—vea la imagen de arriba), pero Chrome informó dos. Parece como si el stick d-pad se informa en Firefox como un eje, pero no parece que los datos salgan de ella. En Chrome, el d-pad apareció como botones adicionales, y se leyó correctamente.
  • timestamp: Por último, este valor es una marca de tiempo que representa la última vez que se comprobó el hardware. En teoría, esto probablemente no es algo que usarías.

De acuerdo, así que es mucho para digerir. En el ejemplo siguiente, simplemente hemos añadido un intervalo para obtener e inspeccionar, el primer mando de juego e imprimir el ID y luego los botones y los ejes:

Puedes probar la demo en Chrome o Firefox.

Supongo que todo esto es bastante autoexplicativo; La única parte realmente difícil era manejar los ejes. Hago un bucle sobre la matriz y cuento por dos para representar los valores de izquierda / derecha, arriba / abajo a la vez. Si abres esto en Firefox y conectas un DualShock, puede ver algo como esto.

Como se puede ver, el botón 2 fue presionado cuando tomé mi captura de pantalla. (En caso de que tengas curiosidad, ese era el botón X.) Tenga en cuenta las palancas; Mi gamepad estaba sentado en mi portátil y esos valores estaban fluctuando constantemente. No de una manera que implicaría que los valores eran malos, per se—si tome el mando del juego y empujé todo el camino en una dirección, vi el valor correcto. Pero creo que lo que estaba viendo era lo sensible que es el controlador para el entorno. O tal vez gremlins.

A continuación, se muestra un ejemplo de cómo Chrome lo muestra:

Yo estaba, otra vez, presionando el botón de X—pero observa cómo el índice del botón es diferente aquí. Como usted puede decir, usted va a necesitar hacer un poco de... masaje si quieres utilizar esta API para un juego. Me imagino que podría comprobar ambos botones 1 y 2 para el "disparo" y haces seguimiento con una buena cantidad de pruebas.

Poniendolo todo junto

Entonces, ¿qué tal una demo real? Al igual que la mayoría de los codificadores que comenzaron su vida jugando videojuegos, soñé con ser un creador de videojuegos importante cuando crecí. Resulta que las matemáticas se ponen muy difíciles después "cálculo", y al parecer esta cosa "web" tiene un futuro, así que mientras que ese futuro no se desarrolló para mí, todavía me gustaría imaginar que un día podría convertir estas habilidades estándares web en un juego jugable. Hasta ese día, lo que tengo hoy es una versión tonta de pong en canvas. Pong de un solo jugador. Como he dicho, tonto.

El juego simplemente hace una paleta y una bola, y le da el control del teclado sobre la pelota. Cada vez que te pierdas la pelota, la puntuación sube. Lo que tiene sentido para el golf en lugar de pong, supongo, pero no nos preocupemos demasiado. El código se puede encontrar en game1.html y puede jugar la demo en tu navegador.

No voy a pasar por todo el código aquí, pero veamos algunos fragmentos. En primer lugar, aquí está la función de bucle principal que maneja todos los detalles de la animación:

La paleta es manejada por el teclado usando dos simples manejadores de eventos:

La variable de entrada input es una variable global que es recogida por un método de movimiento move de objeto paddle:

Una vez más, nada demasiado complejo. Aquí hay una captura de pantalla del juego en acción. (Ya sé—no debería dejar mi trabajo diario.)

Entonces, ¿cómo añadimos soporte de mando de juegos? Afortunadamente, ya tenemos el código hecho. En la demostración anterior, hicimos todo lo necesario para comprobar y recibir actualizaciones del código. Podemos tomar ese código y simplemente añadirlo al código existente del juego.

Dado que es (prácticamente) el mismo, no lo repetiré (aunque el listado completo está disponible si lo desea), pero compartiré el código modificado cada 100ms una vez que se detecte un mando de juegos:

Una vez más, puede probar la demostración en cualquiera de los navegadores.

Al igual que con el ejemplo anterior, hemos asumido que sólo nos interesa un mando de juego. Dado que nuestro juego sólo tiene una paleta y sólo se mueve horizontalmente, podemos obtener por sólo verificando el primer eje. Recuerde, de acuerdo con la API esto debe ser el "más importante", y en mis pruebas fue la palanca izquierda, que es bastante estándar para los juegos.

Dado que nuestro juego utiliza una variable global, input, para representar el movimiento izquierdo y derecho, todo lo que tengo que hacer es modificar ese valor basado en el valor del eje. Ahora, tenga en cuenta que no sólamente comprobamos "menor que cero" y "mayor que cero". ¿Por qué? Si te acuerdas en la demo anterior, el mando de juego era muy sensible, y a menudo reportarían valores incluso cuando no pensaba que realmente había movido la palanca. El uso de un valor límite de 0.5 da al control un poco más de estabilidad. (Y, obviamente, este es el tipo de cosa que tendrías que ajustar para ver que "se siente" bien.)

En general, he añadido aproximadamente 25 líneas de código a mi juego para agregar soporte de mando de juegos. Eso es genial.

¡A jugar!

Esperamos que haya visto que, aunque definitivamente hay algunas idiosincrasias, la API Gamepad ahora tiene soporte en dos grandes navegadores, y es algo que creo que los desarrolladores realmente deberían empezar a considerar para sus juegos.

Recursos

Estos son algunos recursos adicionales que le ayudarán a aprender más sobre la API Gamepad.

Referencias

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.