indigo
indigo copied to clipboard
Examples crashing with Xbox One S controller
Possible bug when using an Xbox One S controller in example games like The Cursed Pirate, Snake or Roguelike Tutorials. Basically pressing any button makes the whole game crash, and if we check the console we can see they are not recognized by GamepadInputCaptureImpl
. In my case I was using the controller connected to a USB port, but I imagine this could happen too using the BT connection. I'm going to check both Indigo code and the examples code to find out what is the problem.
Layout seems to be the same, with the only differences being button names and Xbox controller not featuring the touchpad:
/* Xbox One S layout
Axis Array:
0 left stick X (double 1 is right -1 is left)
1 left stick Y (double 1 is down -1 is up)
2 right stick X (double 1 is right -1 is left)
3 right stick Y (double 1 is down -1 is up)
Buttons Array:
0 A
1 B
2 X
3 Y
4 LB
5 RB
6 LT (Firefox detects this trigger as analog whereas Chrome as button)
7 RT (Same as LT)
8 View
9 Menu
10 Left Stick Press
11 Right Stick Press
12 D Up
13 D Down
14 D Left
15 D Right
16 Xbox Button
*/
Since this button does not exist in Xbox One S controller, GamepadButtons
evaluation crashes. A workaround I've tried successfully is fixing this value to false
, maybe we can read the gamepad number of buttons or infer them from the gamepad id
.
https://github.com/PurpleKingdomGames/indigo/blob/adf1b13b511b0ac8c5db8a6caf46baadf8b5b4d9/indigo/indigo/src/main/scala/indigo/platform/input/GamepadInputCaptureImpl.scala#L78
As per Chromium, the getGamepads
call returns an array of four elements in my case, the first one being the actual gamepad and the others null
:thinking: That means that when trying to evaluate those three null gamepads in the filter(_.connected)
we get a Uncaught TypeError: Cannot read properties of null (reading 'connected')
, which makes sense since there's nothing there.
A sensible workaround for this line: https://github.com/PurpleKingdomGames/indigo/blob/adf1b13b511b0ac8c5db8a6caf46baadf8b5b4d9/indigo/indigo/src/main/scala/indigo/platform/input/GamepadInputCaptureImpl.scala#L52
Could be:
gamepads.find(Option(_).exists(_.connected)) match {
And now I get into an even more intriguing issue, since it seems that pressing one button makes the game think it's never released, and I can't press any other to get it out of this stuck state (this only happens in Chromium, Firefox is working just fine).
Ok so apparently in Chromium/Chrome it's a common practice to call getGamepads
inside the game loop (check out MDN tutorials), somehow it doesn't update the gamepad state internally as Firefox does. Could be interesting to try with other browsers but since right now all of them are effectively FF or Webkit-based I think it is fair to assume this will work exactly the same in Safari and others.
So I'll open a PR including all these changes and resolve the issue.