我用 JavaScript 构建了手柄支持
我花了一个周末的时间,为一款浏览器游戏进行控制器输入的逆向工程。凌晨两点,我盯着一个空数组发呆,什么都没有显示出来。
这次经历比任何教程都让我对浏览器 API 和硬件轮询有了更深的理解。
Web 游戏正在蓬勃发展。随着 WebGL 和 WebGPU 的出现,浏览器游戏的质量已经达到了很高水准。玩家们期望插上 Xbox 或 PS5 控制器后能立即使用。
如果你正在开发游戏、无障碍工具或自定义仪表板,那么你需要了解 HTML5 Gamepad API。它在 Chrome、Firefox 和 Edge 中都能运行,且无需任何库。
以下是我学到的知识:
- 该 API 的连接过程是事件驱动的,但输入过程是基于轮询的。
- 你必须使用
requestAnimationFrame来持续读取输入。 - 在用户按下按钮之前,浏览器不会显示控制器。这是一种防止硬件指纹识别的隐私保护功能。
数据管理:
- 使用
gamepad.mapping来检查是否为“标准”布局。标准映射可以确保按钮 0 始终是底部的面部按钮。 - 检查
gamepad.id以获取厂商 ID (Vendor ID) 和产品 ID (Product ID)。这有助于你识别特定的硬件,例如 Sony DualSense。 - 务必实现死区 (deadzone) 过滤器。摇杆永远不会处于完美的中心位置。如果没有死区设置,你的角色或摄像机将会不断漂移。
处理死区的一种简单方法:
如果 Math.abs(axis) > 0.1,则使用该值。
触觉反馈:
你可以使用 gamepad.vibrationActuator.playEffect 来触发震动。这在 Chrome 和 Edge 中表现良好。Firefox 提供部分支持,而 Safari 则不支持。
项目核心要点:
- 监听
gamepadconnected和gamepaddisconnected事件。 - 追踪之前的按钮状态,以区分“按下 (press)”与“长按 (hold)”。
- 使用死区阈值来忽略微小的摇杆移动。
- 在多个浏览器上进行测试。
- 请记住
navigator.getGamepads()返回的是一个快照。你必须在循环内部调用它才能获取最新数据。
如果你想在编写代码之前测试硬件,可以使用 GamepadTester.pro。它能实时显示原始 API 数据和轴值。
