I'm trying to find joystick state in a cross platform way - developing on windows - using Golang. I'm currently looking to use the joystick API at https://github.com/0xcafed00d/joystick
However, for Go on windows, I don't know how to find the id that I need for joystick.Open(joy_id)
.
Does anyone know of a Go API that allows me to get a list of currently plugged in joysticks/gamepads so I can iterate through their ids? I don't mind if this is just for Windows. N.B. I'm happy to use standard windows libraries or Go packages, but don't want to have to install anything, e.g. SDL 2, since the target users are non technical.
Note 2: I've originally did this with the browser Gamepad API - but the gamepad API is suspended when the browser window is in the background/minimized.
On Windows, I have found that you use an int from 0..3 for xinput controllers (possibly higher for directinput).
Note that the id is allocated when a controller is plugged in and kept (possibly until the OS is restarted). This means that if a controller is disconnected then reconnects, you should get the same id. There is likely an issue if you plug in >4 controllers - I haven't been able to test this.
To get the joysticks states, I did the following (code at the bottom of this post - called with go gamepad.CheckChanged()
):
Note that since the Media API will be used for windows, this detects DualShock 4 and X360 controllers but has the button masks in a different order and also a different number of axes.
I have currently decided not to continue down this route, but hope this helps anyone working on a similar issue.
package gamepad
import (
"fmt"
"time"
"github.com/0xcafed00d/joystick"
)
const MAX_GAMEPAD = 8
type Gamepad struct {
last_buttons uint32
last_axes []int
joystick joystick.Joystick
}
var gamepads [MAX_GAMEPAD]Gamepad
func gamepadUpdate(num int) {
gamepad := gamepads[num]
if joystick := gamepad.joystick; joystick != nil {
state, err := joystick.Read()
if err == nil {
buttons := state.Buttons
if gamepad.last_buttons != buttons {
fmt.Println(state.Buttons)
gamepads[num].last_buttons = buttons
}
} else { // dropped
gamepads[num].last_buttons = 0
gamepads[num].joystick = nil // to avoid reading
fmt.Println(num, " Lost...")
}
}
}
func checkNewGamepads() {
for {
for num, gamepad := range gamepads {
if gamepad.joystick == nil {
js, err := joystick.Open(num)
if err == nil {
_, err := js.Read()
if err == nil {
gamepads[num].joystick = js
gamepads[num].last_buttons = 0
fmt.Println("Opened gamepad ", num)
fmt.Println(" Name: ", js.Name())
fmt.Println(" # buttons : ", js.ButtonCount())
fmt.Println(" # axes : ", js.AxisCount())
}
}
}
// else do nothing since we already have a handle
}
time.Sleep(time.Second / 2) // check 2 times a second for new joysticks
}
}
func CheckChanged() {
go checkNewGamepads() // runs until application exits
for {
// fmt.Print(".")
gamepadUpdate(0)
gamepadUpdate(1)
time.Sleep(time.Second / 60) // 60 times a second
}
}