This page is just a test of the Gamepad API, and a dumping ground for my notes of the raw API.
The test code is very straightforward, and is just intended as a reference to help me see what the data out of the API looks like and therefore how to consume it at a raw level. It's essentially this:
JSON.stringify(
[...navigator.getGamepads()]
.filter(p => p)
.map(pad => ({
index: pad.index,
id: pad.id,
mapping: pad.mapping,
axes: pad.axes,
buttons: [...pad.buttons].map(b => ({
pressed: b.pressed,
touched: b.touched,
value: b.value
})),
vibrationActuator: pad.vibrationActuator
})),
null,
2
);
(source)
It runs on a loop so I can see gamepad activity in realtime. And I must say, there's something satisfying about just seeing gamepad updated in realtime on a web page, even if it's not doing anything "meaningful" yet.
A few notable points:
- The key mappings on a same controller differ on Windows/ChromeOS
- The d-pad on ChromeOS register as a set of axes; as buttons on Windows
- The L/R rudders on ChromeOS also register as axes; as buttons with values on Windows
- Rumble strength and responsiveness is highly dependent on the OS and/or mobility. (My Pixelbook rumble's the controller very sluggishly as compared to my desktop running Windows.)
- The joystick axes are not reliably calibrated to
0
. They consistently hover around 1% off center, and can sometimes be seen sitting idly around 5% off center. - ChromeOS appears to merge rumble magnitudes in some way, whereas Windows simply gives precende to the "weak" (fast) rumble.
- The returned Gamepad objects aren't "live", so you need to call
navigator.getGamepads()
on a loop to watch for updates.
Some mappings appear consistent enough to depend on them out of the gate, such as the left joystick and A, B, X, Y buttons. I'll likely just assume these mappings are correct as I build out functional experiments and sample games. And when I need more buttons, I'll have to experiment between a few different browsers and physical devices to check for consistency.
It probably goes without saying, but the Gamepad API is pretty raw — in that the interface doesn't provide much "semantic help". You get axes
data, buttons
data, and the distinction between the two isn't even always consistent. (Point #3) There's also no event-based interface that I can see. And with the joysticks not being very well calibrated to the zero position, I'll need to build a good abstraction layer.
I'm sure there are already good abstraction libraries out there. And I may poke around for one. But, getting something simple off the ground seems reasonably tractible, and I usually opt to "roll my own" for tractible problems, rather than take on a dependency. But, we'll see. 🤷 ... As a general rule, I enjoy writing my own abstractions about a thousand times more than I enjoy learning and managing dependencies.
If data shows an empty array ([]
) and you have a gamepad plugged in, press one of its buttons!