Gamepad API: Button events not firing

2019-07-28 06:46发布

问题:

I have a bluetooth controller in which I've tested all the numbers of the buttons with this Gamepad tester: http://html5gamepad.com/, so I'm pretty sure the values of the buttons are correct. However, nothing seems to fire, the Gamepad is shown to be "connected", just the button events not working. Below is the code:

function gameLoop() {
  if (navigator.webkitGetGamepads) {
    var wgp = navigator.webkitGetGamepads()[0];

    if (wgp.buttons[12] == 1 || wgp.buttons[4] == 1) {
      console.log('move');
    }
};

gameLoop();

Where could I have wrong? I'm using Chrome so I have the webkit prefix. Could the Gamepad tester be showing me the wrong buttons? Thanks for your help.

回答1:

Had similar issue. Inspecting the code at gamepad.js/all.js.cofee highlighted that we need to retrieve gamepads from navigator on every update cycle (they don't auto-update), make sure your gameLoop() is called repeatedly. For example in window.setInterval(gameLoop, 100) or window.requestAnimationFrame(gameLoop)

Reference:

import * as React from 'react';

interface SampleComponentState {}
class SampleComponent extends React.Component<React.CSSProperties, SampleComponentState>{

    private gamepadUpdateToken: number | null
    constructor(props?: React.CSSProperties){
        super(props)
    }

    private handleGamepad() {
        const gamepads: Gamepad[] = navigator.getGamepads ? 
            navigator.getGamepads() : 
            ((navigator as any).webkitGetGamepads ? (navigator as any).webkitGetGamepads() : [])
        if (gamepads.length == 0){ return }

        gamepads[0].buttons.forEach((button, index) => {
            if (button.pressed){
                console.log(`Pressed button ${index}`)
            }
        })

        gamepads[0].axes.forEach((axe, index) => {
            if (axe != 0){
                console.log(`Axe ${index} moved: ${axe}`)
            }
        })
    }

    componentDidMount(){
        this.gamepadUpdateToken = window.setInterval(this.handleGamepad, 100)
        window.addEventListener("gamepadconnected", (event: any) => {
            const newGamapad: Gamepad = event.gamepad
            console.log(newGamapad)
        })
    }

    componentWillUnmount() {
        window.removeEventListener("gamepadconnected")
        if (this.gamepadUpdateToken != null){
            window.clearInterval(this.gamepadUpdateToken)
        }
    }

    render(){
        return (
            <div>
            </div>
        )
    }
}