8

I would like to provide gamepad support for my web application. This application is a socket client (using socket.io) and it should also being able to deal with gamepad input.

So when plugging in a gamepad via USB or Bluetooth I would like to fire an event, same for input. I was hoping that the Gamepad API would solve it. Unfortunately it didn't.

I created this example

$(document).ready(() => {
  window.addEventListener("gamepadconnected", e => {
    console.log("connected gamepad");
  });

  window.addEventListener("gamepaddisconnected", e => {
    console.log("disconnected gamepad");
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

I plug in my XBox360 controller but unfortunately no event was fired. Am I missing something?

I use Chrome Version 76.0.3809.132 (Official Build) on Manjaro Linux (64-bit)

When running navigator.getGamepads() in the console I get this result GamepadList {0: null, 1: null, 2: null, 3: null, length: 4}

And btw. of course my controller is working on other applications e.g. games :)


Update

I installed Firefox 68.0.1 (64-bit) and it worked... but Chromium seems to struggle

Question3r
  • 2,166
  • 19
  • 100
  • 200
  • What browser do you test on? – Ömürcan Cengiz Nov 29 '19 at 22:16
  • Hey, I'm using chrome – Question3r Nov 30 '19 at 08:25
  • Hey, I was messing around with my Logitech G29 and Twin joystick and these events triggered without any problem on my Chrome(78.0.3904.108). Is the controller recognized by the system? What is your OS? Try running navigator.getGamepads() in the console when the gamepad is connected. – Temo Tchanukvadze Dec 01 '19 at 18:54
  • Hey :) I updated my post .. unfortunately it didn't help.. – Question3r Dec 01 '19 at 20:38
  • 3
    Have you read this question: https://stackoverflow.com/questions/10839310/html5-gamepad-api-on-chrome? – David Thomas Dec 01 '19 at 20:40
  • 1
    This is working for me perfectly on Firefox 70.0.1 on Arch Linux with an Xbox 360 USB gamepad. Does your controller work in other applications? – Darkhogg Dec 01 '19 at 20:42
  • Ok I installed Firefox 68.0.1 (64-bit) and it worked there ... – Question3r Dec 02 '19 at 06:22
  • Did you tried https://github.com/thinkpixellab/PxGamepad try to register first than bind all events with window – Nasiruddin Saiyed Dec 02 '19 at 07:34
  • 3
    As mentioned above, you need to press a gamepad button before Gamepad API will expose any information about connected gamepads. This includes gamepadconnected events. Info about connected devices can be used to fingerprint the user, so to protect your privacy, Chrome won't tell the page about your gamepads unless you're actually using one of them. – nondebug Dec 03 '19 at 03:48

1 Answers1

1

TLDR

  1. Refresh gamepad status in a loop and build your own events.
  2. Remind players to press button on their gamepad to get started.

I wrote a little experiment with the Gamepad API, which I have running on thepointless.com. The full source is available on Github.

Essentially, my experiment does the following in a loop and just prints the output to the screen:

JSON.stringify(
    [...navigator.getGamepads()]
    .filter(p => p)
    .map(pad => ({
        index: pad.index,
        id: pad.id,
        mapping: pad.mapping,
        axes: pad.axes,
        buttons: [...pad.buttons].map(b => ({
            pressed: b.pressed,
            touched: b.touched,
            value: b.value
        })),
        vibrationActuator: pad.vibrationActuator
    })),
    null,
    2
);

In my writeup, I've noted a few things that I anticipate will be generally helpful for working with the API. But, of more relevance to the OP:

  1. The event listeners are a little unreliable.
  2. Gamepads are not accessible via navigator.getGamepads() until a gamepad button is pressed.
  3. The gamepad objects returned by navigator.getGamepads() are not "live"; you actually need to re-fetch them to gate latest axis and button status.

For those reasons, and particularly because you always need to query navigator.getGamepads() to refresh button/axes statuses anyway, any serious work I do with the API will always re-query for gamepads in my game loop, then check statuses, and instruct users to press a gamepad button if gamepads can't be found. If I need "events", I'll build out my own.

I would suggest others do that same.

svidgen
  • 13,744
  • 4
  • 33
  • 58