如何在 Javascript 中创建通用 "joystick/gamepad event"?

How to create a generic "joystick/gamepad event" in Javascript?

问题:
在现代浏览器的当前实现中,(如 Firefox 或 Chrome),只有两个 joystick/gamepad 事件:

由于在浏览器中实现 joystick/gamepad 支持的最初想法似乎是允许浏览器内游戏,因此操纵杆依赖于 requestAnimationFrame() 调用以创建游戏循环同步与 v_sync.

但是,在其他用例中,例如使用操纵杆通过网络或无线连接远程控制某物的情况,最好的情况是仅在有有用的东西要说时才发送数据 - 发生了什么事?使用 requestAnimationFrame() 会使界面充满潜在无用的数据。

不幸的是,目前还没有用于触发游戏手柄事件的既定接口。 :(注意,在 Mozilla 和 W3C 论坛上有一些关于这个问题的讨论,所以这可能 最终, 变化.)

由于用无用的消息淹没工业设备或远程控制系统不是“最佳实践”- 问题变成了如何在不淹没网络或使浏览器停止等待的情况下生成与游戏手柄事件等效的事件-循环。

Webworkers 是一个想法,但不能使用它们,因为它们无法访问 window.event 上下文并且无法与 joystick/gamepad 交互。至少不是直接的。

为了有效地处理这个问题,一些触发“事件”的方法允许数据被发送,只有当感兴趣的事情发生时。

为了那些可能遇到同样问题的人的利益,这是我最终实施的解决方案:

=======================

我的解决方案:
该解决方案基于以下事实:游戏手柄的 time_stamp 属性 仅在发生某些事情时发生变化 。 (按下按钮或移动操纵杆轴,)

  1. 跟踪游戏手柄的 time_stamp 属性并在初始游戏手柄连接事件中捕获它。
  2. 提供围绕实际将数据发送到接收设备的例程的“网关”条件。

我按照上面提到的两个步骤实现了这个:

第一个:
当游戏手柄连接时,我立即捕获 time_stamp 属性并将其存储在变量中 (old_time)。

window.addEventListener("gamepadconnected", (event) => {
    js = event.gamepad;
    gamepad_connected();  // Gamepad is now connected
    old_time = gopigo3_joystick.time_stamp  // Capture the initial value of the time_stamp
    send_data(gopigo3_joystick)  // send it to the robot

然后我做任何我需要做的数据循环和处理。

作为该循环的一部分,我定期尝试使用以下代码将数据发送到服务器设备:

function is_something_happening(old_time, gopigo3_joystick) {
    if (gopigo3_joystick.trigger_1 == 1 || gopigo3_joystick.head_enable == 1) {
        if (old_time != Number.parseFloat(jsdata.timestamp).toFixed()) {
            send_data(gopigo3_joystick)
            old_time = gopigo3_joystick.time_stamp
        }
    }
    return;
}

function send_data(gpg_data) {
// this sends a gamepad data frame to the robot for interpreting.
    [code goes here];
    return;
}

第一个函数 is_something_happening 测试两个合格条件:

  • 按下特定的操纵杆按钮。在没有按下触发器的情况下不允许机器人移动,因此不会发送任何数据。 “head_enable”是允许发送头部平移和倾斜命令消息的另一个条件。
  • time_stamp 值发生变化。如果 time_stamp 值没有改变,则没有发生任何有趣的事情。

两个条件必须满足,否则测试失败,立即returns.

只有当两个条件都满足时,才会调用 send_data() 函数。

这会产生一个稳定的接口,如果发生了有趣的事情,它总是被调用,但是 只有 如果发生了有趣的事情.

注意:有些键盘命令可以发送,但由于它们有活动事件,它们可以自己调用 send_data(),因为它们仅在按下键时触发。