Gamepad API web: DirectInput, XInput y la confusión del mapeo

Qué te da la Gamepad API

La Gamepad API del navegador expone los controles conectados mediante navigator.getGamepads(), que devuelve un array de objetos Gamepad. Cada objeto tiene un array buttons — cada entrada es un objeto con pressed, touched y un value analógico de 0 a 1 — y un array axes con las posiciones de los sticks analógicos, cada una de -1 a 1. Hay eventos gamepadconnected y gamepaddisconnected, pero el estado de botones y ejes nunca se te envía: tienes que sondearlo.

En la práctica eso significa leer el control dentro de un bucle requestAnimationFrame, una vez por fotograma, y comparar este fotograma con el anterior para detectar un botón recién pulsado o soltado. El objeto que obtienes es una instantánea congelada, así que llamas a getGamepads() de nuevo cada fotograma para valores frescos. Este modelo de sondeo es lo primero que sorprende a quienes vienen de eventos de teclado o puntero.

El 'standard mapping'

La especificación define una disposición canónica llamada standard mapping. Cuando un control la cumple, gamepad.mapping es la cadena standard, y los índices son fijos y predecibles: buttons[0] es el botón frontal inferior (A / cruz), buttons[1] el de la derecha (B / círculo), y los bumpers, gatillos, cruceta y clics de stick están en posiciones definidas, con axes[0] a axes[3] para los sticks izquierdo y derecho. Diecisiete botones y cuatro ejes en un orden conocido.

Cuando gamepad.mapping es una cadena vacía, el control no cumplió la disposición estándar y ninguno de esos índices está garantizado. El mismo botón físico puede caer en otro índice, un gatillo puede aparecer como eje y la cruceta puede ser un único eje tipo hat en vez de cuatro botones. La propiedad mapping es el campo más importante que hay que comprobar antes de fiarte de cualquier índice.

DirectInput frente a XInput: la raíz de la confusión

En Windows hay dos formas en que un juego habla con un control. XInput es la API moderna de Microsoft, construida en torno al control de Xbox y la disposición que sigue todo mando compatible con Xbox. Como esa disposición es fija, los navegadores pueden mapear un dispositivo XInput limpiamente sobre el standard mapping — por eso un control de Xbox 'simplemente funciona' en un juego web.

DirectInput es la API más antigua y genérica para cualquier control HID (dispositivo de interfaz humana): muchos mandos de terceros, sticks de arcade, joysticks de vuelo, volantes y controles antiguos o sin marca. DirectInput no impone un orden fijo de botones, así que el navegador no tiene disposición canónica que mapear y reporta un mapping vacío. Esa única diferencia es el origen de casi todo reporte de 'mis botones están revueltos en el navegador'.

Por qué el mismo botón reporta índices distintos

Con un mando DirectInput, el fabricante decide qué control físico es el 'botón 1', así que tu botón A puede llegar como buttons[2], los gatillos pueden aparecer dentro del array axes en vez de como botones, y la cruceta puede reportarse como un hat de punto de vista (POV) — un eje con ocho direcciones — en lugar de cuatro botones separados.

Para hacer usables estos dispositivos, cada navegador aplica sus propias heurísticas de remapeo, y no siempre coinciden: el mismo control DirectInput puede producir índices distintos en Chrome y Firefox. XInput esquiva todo el problema porque Microsoft fijó la disposición, y por eso 'usa un control estilo Xbox' es el consejo más fiable para juegos web.

Cómo manejarlo en código

El patrón robusto es comprobar gamepad.mapping primero. Si vale standard, puedes usar índices con nombre sin riesgo. Si está vacío, no codifiques nada a mano — ofrece una pantalla de remapeo que pida al jugador pulsar cada acción para aprender la disposición de ese dispositivo, y guarda el resultado con la clave gamepad.id para que persista por control.

Dos detalles más importan sin importar el mapping. Los sticks analógicos rara vez descansan exactamente en cero, así que aplica una pequeña zona muerta (normalmente alrededor de 0.1) y trata todo lo de dentro como sin entrada, o la deriva moverá al personaje solo. Y como la API es por sondeo, lee el control fresco cada fotograma y compáralo con el anterior para convertir el estado continuo en eventos discretos de 'recién pulsado'. El probador de mandos de este sitio muestra los índices de botón y valores de eje crudos que reporta tu dispositivo — la forma más rápida de ver si tiene mapeo estándar.

Conclusiones

Comprueba siempre mapping antes de fiarte de los índices. Standard significa la disposición de la especificación; vacío significa específico del dispositivo.

Prefiere controles XInput / estilo Xbox para juegos web — mapean a la disposición estándar, mientras que los DirectInput no.

Nunca codifiques índices a mano para mandos no estándar. Ofrece una UI de remapeo y guarda el resultado por gamepad.id.

Aplica una zona muerta a los ejes para que los sticks en reposo no cuenten como movimiento.

Sondea cada fotograma y compara — para botones y ejes la Gamepad API te da estado, no eventos.