Implement Gamepad API for JavaScript (working on Firefox so far)

This commit is contained in:
Hajime Hoshi 2015-01-12 14:36:13 +09:00
parent a500d3a3f8
commit 8987f7a645
4 changed files with 64 additions and 13 deletions

View File

@ -29,6 +29,7 @@ const (
) )
func update(screen *ebiten.Image) error { func update(screen *ebiten.Image) error {
// TODO: API to get the available, lowest ID
const gamepadID = 0 const gamepadID = 0
axes := []string{} axes := []string{}
pressedButtons := []string{} pressedButtons := []string{}

View File

@ -37,33 +37,33 @@ func (i *input) update(window *glfw.Window, scale int) error {
x, y := window.GetCursorPosition() x, y := window.GetCursorPosition()
i.cursorX = int(math.Floor(x)) / scale i.cursorX = int(math.Floor(x)) / scale
i.cursorY = int(math.Floor(y)) / scale i.cursorY = int(math.Floor(y)) / scale
for j := glfw.Joystick(0); j < glfw.Joystick(len(i.gamepads)); j++ { for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ {
if !glfw.JoystickPresent(j) { if !glfw.JoystickPresent(id) {
continue continue
} }
axes32, err := glfw.GetJoystickAxes(j) axes32, err := glfw.GetJoystickAxes(id)
if err != nil { if err != nil {
return err return err
} }
i.gamepads[j].axisNum = len(axes32) i.gamepads[id].axisNum = len(axes32)
for a := 0; a < len(i.gamepads[j].axes); a++ { for a := 0; a < len(i.gamepads[id].axes); a++ {
if len(axes32) <= a { if len(axes32) <= a {
i.gamepads[j].axes[a] = 0 i.gamepads[id].axes[a] = 0
continue continue
} }
i.gamepads[j].axes[a] = float64(axes32[a]) i.gamepads[id].axes[a] = float64(axes32[a])
} }
buttons, err := glfw.GetJoystickButtons(j) buttons, err := glfw.GetJoystickButtons(id)
if err != nil { if err != nil {
return err return err
} }
i.gamepads[j].buttonNum = len(buttons) i.gamepads[id].buttonNum = len(buttons)
for b := 0; b < len(i.gamepads[j].buttonPressed); b++ { for b := 0; b < len(i.gamepads[id].buttonPressed); b++ {
if len(buttons) <= b { if len(buttons) <= b {
i.gamepads[j].buttonPressed[b] = false i.gamepads[id].buttonPressed[b] = false
continue continue
} }
i.gamepads[j].buttonPressed[b] = glfw.Action(buttons[b]) == glfw.Press i.gamepads[id].buttonPressed[b] = glfw.Action(buttons[b]) == glfw.Press
} }
} }
return nil return nil

View File

@ -16,6 +16,10 @@
package ui package ui
import (
"github.com/gopherjs/gopherjs/js"
)
func (i *input) keyDown(key int) { func (i *input) keyDown(key int) {
k, ok := keyCodeToKey[key] k, ok := keyCodeToKey[key]
if !ok { if !ok {
@ -59,3 +63,36 @@ func (i *input) mouseUp(button int) {
func (i *input) mouseMove(x, y int) { func (i *input) mouseMove(x, y int) {
i.cursorX, i.cursorY = x, y i.cursorX, i.cursorY = x, y
} }
func (i *input) updateGamepads() {
gamepads := js.Global.Get("navigator").Call("getGamepads")
l := gamepads.Get("length").Int()
for id := 0; id < l; id++ {
gamepad := gamepads.Index(id)
if gamepad == js.Undefined || gamepad == nil {
continue
}
axes := gamepad.Get("axes")
axesNum := axes.Get("length").Int()
i.gamepads[id].axisNum = axesNum
for a := 0; a < len(i.gamepads[id].axes); a++ {
if axesNum <= a {
i.gamepads[id].axes[a] = 0
continue
}
i.gamepads[id].axes[a] = axes.Index(a).Float()
}
buttons := gamepad.Get("buttons")
buttonsNum := buttons.Get("length").Int()
i.gamepads[id].buttonNum = buttonsNum
for b := 0; b < len(i.gamepads[id].buttonPressed); b++ {
if buttonsNum <= b {
i.gamepads[id].buttonPressed[b] = false
continue
}
i.gamepads[id].buttonPressed[b] = buttons.Index(b).Get("pressed").Bool()
}
}
}

View File

@ -47,6 +47,7 @@ func DoEvents() error {
for !shown() { for !shown() {
vsync() vsync()
} }
currentInput.updateGamepads()
return nil return nil
} }
@ -66,9 +67,10 @@ func init() {
// TODO: Implement this with node-webgl mainly for testing. // TODO: Implement this with node-webgl mainly for testing.
doc := js.Global.Get("document") doc := js.Global.Get("document")
window := js.Global.Get("window")
if doc.Get("body") == nil { if doc.Get("body") == nil {
ch := make(chan struct{}) ch := make(chan struct{})
js.Global.Get("window").Call("addEventListener", "load", func() { window.Call("addEventListener", "load", func() {
close(ch) close(ch)
}) })
<-ch <-ch
@ -127,6 +129,7 @@ func init() {
canvas.Call("setAttribute", "tabindex", 1) canvas.Call("setAttribute", "tabindex", 1)
canvas.Get("style").Set("outline", "none") canvas.Get("style").Set("outline", "none")
// Keyboard
canvas.Call("addEventListener", "keydown", func(e js.Object) bool { canvas.Call("addEventListener", "keydown", func(e js.Object) bool {
code := e.Get("keyCode").Int() code := e.Get("keyCode").Int()
currentInput.keyDown(code) currentInput.keyDown(code)
@ -137,6 +140,8 @@ func init() {
currentInput.keyUp(code) currentInput.keyUp(code)
return false return false
}) })
// Mouse
canvas.Call("addEventListener", "mousedown", func(e js.Object) bool { canvas.Call("addEventListener", "mousedown", func(e js.Object) bool {
button := e.Get("button").Int() button := e.Get("button").Int()
currentInput.mouseDown(button) currentInput.mouseDown(button)
@ -150,6 +155,14 @@ func init() {
canvas.Call("addEventListener", "contextmenu", func(e js.Object) bool { canvas.Call("addEventListener", "contextmenu", func(e js.Object) bool {
return false return false
}) })
// Gamepad
window.Call("addEventListener", "gamepadconnected", func(e js.Object) {
print(e)
})
window.Call("addEventListener", "gamepaddisconnected", func(e js.Object) {
print(e)
})
} }
func devicePixelRatio() int { func devicePixelRatio() int {