【问题标题】:How to detect a button press with Gamepad API?如何使用 Gamepad API 检测按钮按下?
【发布时间】:2021-07-15 11:16:23
【问题描述】:

我正在尝试编写一个网页,我可以在其中检测 Xbox 控制器上的按钮按下,并根据按下的按钮向用户显示一个布尔值。现在,我可以检测到正在连接的控制器并将其显示为字符串。文档说在这里使用此代码来检测按钮按下:

var isPressed = navigator.getGamepads()[0].pressed;

但 Chrome 在使用时显示此错误:

Uncaught TypeError: Cannot read property 'pressed' of null

错误链接到上述代码行的.pressed 部分。 All the documentation is on the Mozilla site,所以我假设他们在编写教程时使用了 FireFox。

我最理想的结果是:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<h id="button"></h>
<h id="gpInfo"></h>
<script>
var i = 1; 
window.addEventListener("gamepadconnected", function(e) {
  var gp = navigator.getGamepads()[e.gamepad.index];
  document.getElementById("gpInfo").innerHTML = ("A " + gp.id + " was successfully detected! There are a total of " + gp.buttons.length + " buttons.")
  //alert("A " + gp.id + " was successfully detected!")
});
var isPressed = navigator.getGamepads()[0].pressed;
document.getElementById("button").innerHTML = isPressed;
</script>
<!-- <script type="text/javascript" src="gamepadtest.js"></script> -->
</head>
</html>

代码会在屏幕上打印一个布尔值,供用户在按下按钮时查看。 这是我第一次使用 JavaScript 和 HTML。如果你能让你的答案对菜鸟友好,那就太好了! Gamepad APIGamepadButton 的文档

【问题讨论】:

  • 错误告诉你 navigator.getGamepads()[0] 什么都不是,所以:验证代码中是否有 is 游戏手柄。例如。 const gamepads = navigator.getGamepads(); if (gamepads.length &gt; 0) { const gamepad = ...; /* more code here */ } else { console.warn("there are no gamepads"); }
  • @Mike'Pomax'Kamermans 好的,稍后再试。直到用户按下游戏手柄上的按钮,游戏手柄才会连接。

标签: javascript html gamepad-api


【解决方案1】:

我没有足够的声誉来向 Caleb Denio's answer 添加评论,但关于 Nathan 对该答案的评论:

我用你的例子监听了 20 个按钮,我可以检测到每个按钮,但是一旦我按下了一个按钮,它就不会改变另一个按钮的另一个结果。

我在 Chrome 90 上看到了相同的行为。具体来说,一个新的 GamepadList 实例,包含新的 Gamepad 实例,似乎在每次任何游戏手柄的状态发生变化时都会创建(例如按下哪个按钮)。

你可以用这个来测试它:

var gamepads = null;

function callback() {
    var new_gamepads = navigator.getGamepads();
    if(new_gamepads !== gamepads) {
        console.log('New GamepadList!', new_gamepads);
        gamepads = new_gamepads;
    }
}

var interval = setInterval(callback, 100);

...对我来说,记录“新 GamepadList!”每次按下/释放按钮。

长话短说,您需要在每一帧中轮询navigator.getGamepads() 以检测游戏手柄状态的变化。 因此,对于 Caleb Denio 的回答,一个极简主义的解决方法是:

var i = 1; 
window.addEventListener("gamepadconnected", function(e) {
  var gp = navigator.getGamepads()[e.gamepad.index];
  document.getElementById("gpInfo").innerHTML = ("A " + gp.id + " was successfully detected! There are a total of " + gp.buttons.length + " buttons.")
  //alert("A " + gp.id + " was successfully detected!")

  setInterval(function(){

    // ===> Get a fresh GamepadList! <===
    var gp = navigator.getGamepads()[e.gamepad.index];

    isPressed = gp.buttons[0].pressed;
    document.getElementById("button").innerHTML = isPressed;
  }, 100)
});

【讨论】:

    【解决方案2】:

    在引发 gamepadconnected 事件之前,您不应引用 Gamepad 对象。此外,您需要一个循环来轮询按​​钮值。这是一些修改后的代码:

    var i = 1; 
    window.addEventListener("gamepadconnected", function(e) {
      var gp = navigator.getGamepads()[e.gamepad.index];
      document.getElementById("gpInfo").innerHTML = ("A " + gp.id + " was successfully detected! There are a total of " + gp.buttons.length + " buttons.")
      //alert("A " + gp.id + " was successfully detected!")
    
      setInterval(function(){
        isPressed = gp.buttons[0].pressed;
        document.getElementById("button").innerHTML = isPressed;
      }, 100)
    });
    

    【讨论】:

    • 这很好用,它会检测按钮是否被按下。我怎样才能让它继续检查按钮是否被按下?
    • 它应该继续检查,因为setInterval。它每 100 毫秒运行一次。如果它仍然没有更新,我会在控制台中查找错误。
    • 控制台中没有错误,但在 Elements 中我可以看到它正在更新,但它无法识别我的印刷机。我按下按钮 1 让它显示遥控器,然后按下按钮 0 来改变变量。但事实并非如此,这不是捡起来的吗?如果您需要我的完整代码,请告诉我
    • 此代码仅响应按钮 0 上的更改。我不确定您到底想做什么。
    • 我已经用你的例子监听了 20 个按钮,我可以检测到每个按钮,但是一旦我按下了一个按钮,它不会改变另一个按钮的另一个结果。可以看代码直播here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多