我正在使用250ms计时器在js中轮询Gamepad,以在4个不同的观点之间切换。但是,该值仍然过高,无法保证每按一次按钮。我注意到,如果按下某个按钮并释放得太快(即<250毫秒),则会丢失该按钮。
除了连接和断开控制器外,我看不到任何与游戏手柄相关的事件触发器,而且我陷入了轮询并增加了频率的问题。
有人可以提出一种在不增加轮询频率的情况下保证检测到按钮按下的方法吗?如果增加轮询频率是唯一的选择,那么什么才是最佳的呢?
答案 0 :(得分:1)
您应该以至少60 Hz的频率进行轮询,以确保每个动画帧至少捕获一次新的按钮/轴状态。大多数应用程序都在requestAnimationFrame循环中进行轮询,但这并不总是最好的解决方案,因为您仍然会错过按钮的按下。
最佳轮询率取决于浏览器的内部行为。例如,在Chrome中,浏览器仅每16毫秒(62.5 Hz)获取新的游戏手柄状态,因此,如果以〜100 Hz的频率进行轮询,则可以确保每次更新。如果在两次轮询迭代之间发生按钮按下,仍然可能会错过它们,但是您无能为力。 (几乎没有:Chrome Dev和Canary版本具有chrome:// flags#gamepad-polling-rate选项,可用于测试不同的内部轮询率。)
内部轮询率不是由规范定义的,不会直接暴露给页面,并且可能会发生变化。例如,浏览器可以选择合并游戏手柄输入更新并将它们与requestAnimationFrame循环对齐,这会抵消更频繁轮询的任何好处。依靠特定于实现的行为并测试您的假设时要小心。
在Firefox上,您可以启用非标准的按钮和轴事件,这些事件可以让您检测何时输入更新发生在常规轮询循环之外。 AFAIK这些事件仅在FF上实现,默认情况下处于禁用状态,但对测试很有用。
答案 1 :(得分:0)
Gamepad API确实仅支持轮询,而您的轮询频率确实过低。
假设您正在尝试制作游戏,则理想情况下,游戏手柄的响应速度应与游戏的帧频一样高。这样可以确保始终能捕捉到按下按钮的情况。
JavaScript的requestAnimationFrame
就是为此目的而设计的。
如果您查看neogeek's gamepad.js,您会看到它使用API在每一帧轮询游戏手柄:
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));
}