Reputation: 41
I am polling Gamepad in js using a 250ms timer to switch between 4 different viewpoints. However this value is still too high to guarantee seeing every button press. I have noticed that if a button is depressed and released too quickly (i.e., < 250ms) then it gets missed.
I can't see any event triggers related to gamepad apart from controller connected and disconnected, and I am stuck with polling, and increasing the frequency.
Can anybody propose a method of guaranteeing a button press is detected, without increasing the polling frequency? If increasing the polling frequency is the only option, what would be considered optimal?
Upvotes: 4
Views: 2868
Reputation: 1031
You should poll at (at least) 60 Hz to ensure you capture new button/axis state at least once per animation frame. Most apps poll in the requestAnimationFrame loop but this isn't always the best solution because you can still miss button presses.
The optimal polling rate is determined by the browser's internal behavior. In Chrome for instance, the browser only fetches new gamepad state every 16 milliseconds (62.5 Hz), so if you poll at ~100 Hz then you will be sure to see every update. It's still possible to miss button presses if they occur between polling iterations, but there's nothing you can do about that. (Almost nothing: Chrome Dev and Canary builds have a chrome://flags#gamepad-polling-rate option you can use to test different internal polling rates.)
The internal polling rate is not defined by the spec, is not directly exposed to the page, and is subject to change. For instance, a browser could choose to coalesce gamepad input updates and align them to the requestAnimationFrame loop which would negate any benefits from polling more frequently. Be cautious when relying on implementation-specific behavior and test your assumptions.
On Firefox you can enable non-standard button and axis events which may let you detect when input updates occur outside your normal polling loop. AFAIK these events are only implemented on FF and are disabled by default, but could be useful for testing.
Upvotes: 2
Reputation: 7563
The Gamepad API indeed only supports polling, and your polling frequency is indeed too low.
Assuming you're trying to build a game, the gamepad responsiveness would ideally be as high as the game's frame rate. This would make sure that a button press would always be caught.
Javascript's requestAnimationFrame
is intended for this very purpose.
If you take a look at neogeek's gamepad.js, you'll see it uses the API to poll the gamepad at every frame:
Gamepad.prototype._loop = function () {
...
self._events.gamepad.forEach(function (gamepad, player) {
if (gamepad) {
Object.keys(gamepad).forEach(function (key) {
self._handleEvent(key, gamepad, player);
});
}
});
...
self._requestAnimation = _requestAnimationFrame(self._loop.bind(self));
}
Upvotes: 1