Advertisement
  1. Web Design
  2. HTML/CSS
  3. HTML

Introducción a la API de Gamepad de HTML5

Scroll to top
Read Time: 12 min

() translation by (you can also view the original English article)

A medida que los juegos HTML comienzan a aumentar gradualmente en popularidad, los proveedores están comenzando a introducir algunas API nuevas y emocionantes para hacer que los juegos sean un poco más dulces tanto para los desarrolladores como para nuestros jugadores finales. Una de ellas es la API de Gamepad, que te permite conectar tu viejo control de consola a tu computadora y usarlo para juegos basados ​​en navegador, al estilo 'enchufar y usar'. ¡Empecemos!


Introducción: ¿Qué es la API de Gamepad?

En pocas palabras, la API de Gamepad te permite interactuar con tu navegador usando un controlador de consola de videojuegos, también conocido como un 'gamepad' o 'control de videojuegos'. Esto no requiere un controlador o complemento especial para funcionar, ¡es tan simple como enchufar y usar!

Como soy un jugador de consola y no de escritorio, prefiero interactuar con los juegos usando un gamepad, y con el próximo auge de los juegos basados ​​en HTML y JavaScript, esto se convertirá en una herramienta realmente útil para hacer que los juegos sean más accesibles para tus usuarios.

La API de Gamepad no está disponible para su lanzamiento público, pero podemos comenzar a usarla nosotros mismos con versiones de vista previa de Firefox. Entonces, antes de sumergirnos, necesitaremos algunas cosas.


Lo que necesitarás

Como mencioné, la API de Gamepad aún no está disponible para su lanzamiento público, por lo que primero deberás obtener una compilación Nightly de Firefox y asegurarte de tener instalado el complemento de Firebug (solo para fines de depuración).

Además, ¡no puedes olvidar un gamepad! Voy a usar un controlador de PlayStation 3 para este tutorial, pero un controlador de Xbox funcionará bien.

Una vez que hayas instalado Nightly y agregado Firebug, ¡estarás preparado para comenzar!

(Nota: Las compilaciones recientes de Chromium también son compatibles con la API de Gamepad, pero este tutorial no se ha probado con ellas).


Paso 1: Conectar un Gamepad al navegador

Comencemos con un archivo HTML básico (index.html), obteniendo "gamepad.js" (un archivo JavaScript en blanco).

index.html

1
<!doctype html>
2
<html>
3
  <head>
4
    <meta charset="utf-8">
5
    <title>Introduction to the Gamepad API</title>
6
  </head>
7
  <body>
8
    <h1>Gamepad API</h1>
9
10
    <script src="gamepad.js"></script>
11
  </body>
12
</html>

La conexión de un gamepad se detecta con un detector de eventos JavaScript simple, el evento disparado se llama "MozGamepadConnected". Entonces, lo primero que debemos hacer es agregar un detector de eventos a la ventana para detectar ese evento.

También estoy agregando una función de devolución de llamada que registrará los detalles del evento en la consola de Firebug. Esta es la información que más nos interesa y lo que realmente nos permitirá saber que hemos conectado un gamepad con éxito.

1
function gamepadConnected(evt)
2
{
3
  console.log(evt); 
4
}
5
window.addEventListener('MozGamepadConnected', gamepadConnected);

Ejecute tu index.html en Nightly y abre la consola de Firebug, aquí podremos ver el registro del evento desde nuestra función de devolución de llamada.

Asegúrate de que tu control esté apagado y no conectado de forma inalámbrica a una consola de juegos. Conéctato a tu computador a través de USB y enciende el control, viendo el registro de eventos en la consola.

The logged event of connecting a gamepadThe logged event of connecting a gamepadThe logged event of connecting a gamepad

Genial, tenemos un gamepad que se conecta a un navegador, ¡no se requieren complementos ni controladores adicionales!


Paso 2: Desconectar un Gamepad

Es igualmente importante saber si un gamepad también se ha desconectado, así que echemos un vistazo al evento "MozGamepadDisconnected".

De manera similar al paso uno, agrega un detector de eventos para un evento de desconexión y una función de devolución de llamada para registrar los detalles del evento.

1
function gamepadDisconnected(evt)
2
{
3
  console.log(evt); 
4
}
5
window.addEventListener('MozGamepadDisconnected', gamepadDisconnected);

Si tu gamepad todavía está conectado, actualiza tu página (verás que se registra el evento conectado) y luego desconecta tu gamepad expulsándolo del puerto USB. Deberías obtener un registro de eventos como este:

The logged event of disconnecting a gamepadThe logged event of disconnecting a gamepadThe logged event of disconnecting a gamepad

Ahora que sabemos que cuando un mando se ha conectado y desconectado, probablemente sea una buena idea registrar el estado dentro de una variable y prepararte para detectar eventos de botones.

1
var gamepadActive = false;
2
3
function gamepadConnected(evt)
4
{
5
  console.log(evt);
6
  gamepadActive = true;
7
}
8
function gamepadDisconnected(evt)
9
{
10
  console.log(evt);
11
  gamepadActive = false;
12
}
13
14
window.addEventListener('MozGamepadConnected', gamepadConnected);
15
window.addEventListener('MozGamepadDisconnected', gamepadDisconnected);

Paso 3: Detectando las pulsaciones de los botones

Las pulsaciones de botones, de nuevo, utilizan un detector de eventos y una función de devolución de llamada con dos eventos, "MozGamepadButtonDown" y "MozGamepadButtonUp".

Sugeriría registrar todo el evento desde el botón que presionas tú mismo para ver qué está pasando, pero la información clave que necesitamos obtener de este evento es evt.button. Esta es la identificación numérica del botón que se presionó.

Esta vez, la función de devolución de llamada toma un segundo parámetro, un valor booleano para probar si se presionó o se soltó el botón. Lo configuramos nosotros mismos en las funciones de devolución de llamada de los oyentes de eventos.

1
function buttonPressed(evt, pressed)
2
{
3
  console.log(evt.button, pressed); 
4
}
5
window.addEventListener("MozGamepadButtonDown", function(evt) { buttonPressed(evt, true); } );
6
window.addEventListener("MozGamepadButtonUp", function(evt) { buttonPressed(evt, false); } );

Esto ahora debería mostrar los ID de los botones que se presionaron y si se presionaron o soltaron (verdadero para el momento en que se presiona el botón, falso cuando se suelta).

The logged button id's

A continuación, crearemos una matriz con todos los botones de PlayStation 3. Los índices de la matriz se asignarán a los ID utilizados en este gamepad, siendo los valores el nombre del botón.

1
var gamepadActive = false,
2
    ps3Buttons = new Array();
3
4
ps3Buttons[12]  = 'triangle',
5
ps3Buttons[15]  = 'square',
6
ps3Buttons[14]  = 'cross',
7
ps3Buttons[13]  = 'circle',
8
ps3Buttons[4]   = 'up',
9
ps3Buttons[7]   = 'left',
10
ps3Buttons[6]   = 'down',
11
ps3Buttons[5]   = 'right',
12
ps3Buttons[10]  = 'L1',
13
ps3Buttons[8]   = 'L2',
14
ps3Buttons[11]  = 'R1',
15
ps3Buttons[9]   = 'R2',
16
ps3Buttons[1]   = 'L3',
17
ps3Buttons[2]   = 'R3',
18
ps3Buttons[16]  = 'PS',
19
ps3Buttons[0]   = 'select',
20
ps3Buttons[3]   = 'start';

Si estás utilizando un control diferente, tómate el tiempo para averiguar qué índice va con qué botón y almacena esa información en una matriz similar.

Si ahora modificamos ligeramente la función buttonPressed(), podemos saber fácilmente qué botón del controlador se ha presionado.

1
function buttonPressed(evt, pressed)
2
{
3
  console.log(ps3Buttons[evt.button] + ' was pressed');
4
}

¡Dale una oportunidad! Presiona los botones en tu control y registra el nombre de los botones que se presionan. Esto será mucho más fácil de entender que el "botón 5" (que, en mi caso, está en el D-pad).


Paso 4: Detectando los eventos de los ejes

La detección de los eventos de los ejes consiste básicamente en realizar un seguimiento de dónde se colocan los joysticks analógicos izquierdo y derecho del gamepad mediante el evento "MozGamepadAxisMove".

Agrega el nuevo controlador de eventos y la función de devolución de llamada.

1
function moveAnalogSticks(evt) {
2
  console.log(evt.axis, evt.value);
3
}
4
window.addEventListener("MozGamepadAxisMove", moveAnalogSticks);

Esto es lo que obtenemos - algo confuso, ¿verdad?

The logged button id'sThe logged button id'sThe logged button id's

Solo hay un evento disparado por ambos sticks analógicos; cada evento nos da uno de los cuatro ejes posibles y un valor entre -1.0 y +1.0. Los ejes 0 y 1 pertenecen al joystick analógico izquierdo y los ejes 2 y 3 pertenecen al de la derecha.

The logged button id'sThe logged button id'sThe logged button id's

En el diagrama de arriba, verás que los ejes 0 y 2 corresponden al eje x, y 1 y 3 corresponden al eje y. Al usar los ejes X e Y para cada palanca analógica individual, ¡puedes averiguar en qué dirección está orientada la palanca analógica!

En diferentes gamepads, es posible que tengas otros ejes. Por ejemplo, los disparadores de un control de Xbox también son analógicos.


Paso 5: Ponlo en práctica

Eso cubre todos los eventos que actualmente podemos tomar de un gamepad, así que pongamos en práctica lo que hemos aprendido.

Ahora, no quiero entrar demasiado en el lado del desarrollo de juegos, ya que nos estamos enfocando en lo que usamos para controlar los juegos en sí. Sin embargo, una de las cosas clave a tener en cuenta es cambiar los esquemas de control. Como no todo el mundo tendrá un mando a mano, debemos asegurarnos de proporcionar controles tanto para el teclado como para el mando.


Paso 6: Configuración de tu Canvas

Para poner en marcha una pequeña demostración, crea un elemento canvas en tu archivo html con un id que sea "game" y establece el ancho en 600 y la altura en 540. Como sabrás, el elemento canvas se usa comúnmente para renderizar juegos en  HTML.

También querrás copiar las imágenes "ship.png" y "space.jpg" de la descarga de origen a tu carpeta de trabajo, ya que estas son las que mostraremos en el canvas. Alternativamente, ¡encuentra algunos gráficos propios para jugar!

1
<!doctype html>
2
<html>
3
  <head>
4
    <meta charset="utf-8">
5
    <title>Introduction to the Gamepad API</title>
6
  </head>
7
  <body>
8
    <h1>Gamepad API</h1>
9
    <canvas id="game" width="600" height="540"></canvas>
10
    <script src="gamepad.js"></script>
11
  </body>
12
</html>

Paso 7: Creando el bucle del juego

Ahora que el elemento canvas está en nuestro DOM, queremos crear un bucle de juego para renderizar nuestro juego.

Estoy usando un pequeño código para el "requestAnimationFrame" de Paul Irish que será la base de nuestro bucle. A continuación, obtenemos el contexto 2D del canvas que usaremos para dibujar y crear dos nuevos objetos de imagen, uno para el fondo y otro para nuestra nave espacial.

1
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/

2
window.requestAnimFrame = (function(){
3
  return  window.requestAnimationFrame       || 
4
          window.webkitRequestAnimationFrame || 
5
          window.mozRequestAnimationFrame    || 
6
          window.oRequestAnimationFrame      || 
7
          window.msRequestAnimationFrame     || 
8
          function(/* function */ callback, /* DOMElement */ element){
9
            window.setTimeout(callback, 1000 / 60);
10
          };
11
})();
12
13
var canvas  = document.getElementById('game'),
14
    ctx     = canvas.getContext('2d'),
15
    ship    = new Image(),
16
    space   = new Image();
17
18
space.src = "space.jpg";
19
ship.src  = "ship.png";

A continuación, el objeto del jugador. Tiene coordenadas "x" e "y" que hacen un seguimiento de dónde debería aparecer en el canvas; cuatro estados de dirección (arriba, abajo, izquierda y derecha) para que podamos saber en qué dirección se mueve la nave; una función render(), que primero llama a updatePosition() y luego dibuja la imagen de la nave en el canvas en función de las coordenadas x e y, y finalmente la función updatePosition() en sí misma, que prueba para ver en qué dirección está configurada la nave para moverse y actualiza su posición en consecuencia.

1
var player = {
2
  x: 200,
3
  y: 250,
4
  up: false,
5
  down: false,
6
  left: false,
7
  right: false,
8
  render: function() {
9
    this.updatePosition();
10
    ctx.drawImage(ship,this.x,this.y);
11
  },
12
  updatePosition: function() {
13
    this.up     ? this.y-- : false;
14
    this.down   ? this.y++ : false;
15
    this.left   ? this.x-- : false;
16
    this.right  ? this.x++ : false;
17
  }
18
}

Después de eso tenemos nuestra función "renderGame" que dibuja la imagen de fondo del espacio en el canvas primero, luego dibuja nuestra nave espacial encima de eso.

Y finalmente, nuestro bucle. Esta función se llama a sí misma una y otra vez, cada vez que llama a nuestra función "renderGame".

1
function renderGame()
2
{
3
  ctx.drawImage(space,0,0);
4
  player.render();
5
}
6
7
;(function animloop(){
8
  requestAnimFrame(animloop);
9
  renderGame();
10
})();

Tu canvas debería tener ahora un bonito fondo de aspecto espacial con una nave espacial en el medio, no demasiado emocionante, lo sé. ¡Así que agreguemos algunos controles!


Paso 8: Conexión de los controles de la nave

En nuestro código de jugador nombramos los cuatro botones con los que queremos controlar nuestra nave. Estos coinciden con los nombres de los botones dentro de la matriz ps3Buttons[]. Entonces, todo lo que tenemos que hacer es modificar ligeramente nuestra función buttonPressed() y nos estaremos moviendo.

1
var player = {
2
  ...
3
  up: false,
4
  down: false,
5
  left: false,
6
  right: false,
7
  ...
8
}

Ahora, cuando se presiona o suelta un botón del gamepad, se establecerá su estado dentro del objeto del jugador, por lo que cuando se presione el botón "arriba", se establecerá player.up = true/false.

1
function buttonPressed(evt, pressed)
2
{
3
  console.log(evt.button, pressed);
4
  player[ps3Buttons[evt.button]] = pressed ? true : false;
5
}

¡Vuelve a tu demo y deberías poder mover tu nave!


Paso 9: Agregar un teclado alternativo

Como no todos los que jueguen tu juego tendrán un mando, probablemente querrás permitirles jugar con un teclado.

Primero creemos una nueva matriz para la teclas llamada keys[] y mapeemos las propiedades keyCode de las teclas de la flecha del teclado con los botones equivalentes en el gamepad. Esto nos permitirá reutilizar la función buttonPressed() que utiliza el gamepad.

1
var gamepadActive = false,
2
    ps3Buttons    = new Array(),
3
    keys          = new Array();
4
5
ps3Buttons[12]  = 'triangle',
6
ps3Buttons[15]  = 'square',
7
ps3Buttons[14]  = 'cross',
8
ps3Buttons[13]  = 'circle',
9
ps3Buttons[4]   = 'up',
10
ps3Buttons[7]   = 'left',
11
ps3Buttons[6]   = 'down',
12
ps3Buttons[5]   = 'right',
13
ps3Buttons[10]  = 'L1',
14
ps3Buttons[8]   = 'L2',
15
ps3Buttons[11]  = 'R1',
16
ps3Buttons[9]   = 'R2',
17
ps3Buttons[1]   = 'L3',
18
ps3Buttons[2]   = 'R3',
19
ps3Buttons[16]  = 'PS',
20
ps3Buttons[0]   = 'select',
21
ps3Buttons[3]   = 'start';
22
23
keys[38] = 4;
24
keys[37] = 7;
25
keys[40] = 6;
26
keys[39] = 5;

Ahora necesitamos un detector de eventos "onkeyup" y "onkeydown" para las teclas de tipo flecha. Cuando se presiona o suelta una tecla, nos aseguramos de que no se esté usando un gamepad. Luego evitamos que la tecla de flecha haga su tarea habitual (desplazar la ventana del navegador hacia arriba o hacia abajo en este caso) y luego llamamos a la misma función buttonPressed() que llama el gamepad.

Para hacer esto, se pasa un objeto de evento falso con el "keyCode" de la clave asignado a un elemento en la matriz keys[], que a su vez, pasa el ID del botón correspondiente del gamepad.

1
window.onkeydown = function(evt)
2
  {
3
    if (gamepadActive == false)
4
    {
5
      evt.preventDefault();
6
      buttonPressed({ button: keys[evt.keyCode] }, true);
7
    }
8
  }
9
window.onkeyup = function(evt)
10
  {
11
    if (gamepadActive == false)
12
    {
13
      evt.preventDefault();
14
      buttonPressed({ button: keys[evt.keyCode] }, false);
15
    }
16
  }

Esto ahora debería permitirte usar las teclas de flecha para controlar la nave cuando un gamepad no está enchufado, mientras dejas que el gamepad tome el control cuando está presente.


Conclusión

Así que hemos cubierto los conceptos básicos de la conexión de un controlador para juegos a tu computadora, aprendimos cómo conectar los eventos que activa el controlador para juegos y luego usarlos en la práctica. Sin olvidar, el soporte alternativo crucial para el teclado.

Un desafío rápido para aquellos de ustedes con un controlador que no sea PS3 Dual Shock: ajustar la asignación de botones en función del controlador que esté conectado.

Gracias por tomarte el tiempo para aprender sobre la API de Gamepad. Si tienes alguna pregunta, déjala en los comentarios.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
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.