-
-
Notifications
You must be signed in to change notification settings - Fork 467
Gamepad Navigation
This page covers different topics related to controling Heroic using a gamepad.
WIP until we have the PR merged
Heroic uses the Gamepad API to detect interactions with the gamepad. Make sure your controller is detected in https://gamepad-tester.com using a chromium-based browser before reporting a controller not working.
This are the currently implemented interactions:
Moves the focus to the next element in the specified direction. Holding the action repeats every 500ms.
Moves the focus to the next element in the specified direction. Holding the action repeats every 250ms.
Scrolls the main content by 50px in the specified direction. Holding the action repeats every 50ms.
It executes the main action associated to the currently focused object:
- Search Input: show and focus the virtual keyboard
- Virtual keyboard buttons: type a letter in the search input
- Game card: if the game is installed, run the game
- anywhere else: acts as a click on the element
It executes a back action in the browser history in most cases to go back to the previous screen. Exceptions are:
- Virtual keyboard is visible: remove keyboard
Executes an alternative action depending on specific conditions:
- Virtual keyboard is visible: delete the last character in the input
- Focused element is the game card: open the game screen
Heroic uses simple-keyboard for the virtual keyboard.
Press the mainAction
button when focusing the search input.
Pressing the mainAction
button when focusing the desired letter will append the letter to the input.
Pressing the altAction
button will remove the last letter from the input.
Pressing the back
button will dismiss the keyboard.
Each gamepad may have its own layout. We need to code the mapping between the generic BX
and axes reported by the Gamepad API to valid actions for each device.
Matches any controller id with the words xbox
or microsoft
in it, or product id 0268
.
B0 = A (mapped as mainAction)
B1 = B (mapped as back)
B2 = X
B3 = Y (mapped as altAction)
B4 = LB
B5 = RB
B6 = LT // supports a `.value` method with a value between 0 and 1
B7 = RT // supports a `.value` method with a value between 0 and 1
B8 = view
B9 = menu
B10 = L3 // pressing the left stick
B11 = R3 // pressing the right stick
B12 = Dpad Up (mapped as padUp)
B13 = Dpad Down (mapped as padDown)
B14 = Dpad Left (mapped as padLeft)
B15 = Dpad Right (mapped as padRight)
B16 = XBOX
AXIS 0 = leftAxisX (mapped as leftStickLeft and leftStickRight) // -1 = left, 1 = right
AXIS 1 = leftAxisY (mapped as leftStickUp and leftStickDown) // -1 = up, 1 = down
AXIS 2 = rightAxisX // -1 = left, 1 = right
AXIS 3 = rightAxisY (mapped as rightStickUp and rightStickDown) // -1 = up, 1 = down
Matches any controller id with the words PS3
, PS4
, PS5
, PLAYSTATION
or SONY
in it, or product ids 0268
and 0c36
.
B0 = X (mapped as mainAction)
B1 = Circle (mapped as back)
B2 = Triangle (mapped as altAction)
B3 = Square
B4 = LB
B5 = RB
B6 = LT // gets "pressed" as soon as the trigger is moved down slightly
B7 = RT // gets "pressed" as soon as the trigger is moved down slightly
B8 = Select
B9 = Start
B10 = PS Button
B11 = L3 // pressing the left stick
B12 = R3 // pressing the right stick
B13 = Dpad Up (mapped as padUp)
B14 = Dpad Down (mapped as padDown)
B15 = Dpad Left (mapped as padLeft)
B16 = Dpad Right (mapped as padRight)
AXIS 0 = leftAxisX (mapped as leftStickLeft and leftStickRight) // -1 = left, 1 = right
AXIS 1 = leftAxisY (mapped as leftStickUp and leftStickDown) // -1 = up, 1 = down
AXIX 2 = LT // reports LT pressed value between -1 (not pressed) and 1 (fully pressed)
AXIS 3 = rightAxisX // -1 = left, 1 = right
AXIS 4 = rightAxisY (mapped as rightStickUp and rightStickDown) // -1 = up, 1 = down
AXIX 5 = RT // reports RT pressed value between -1 (not pressed) and 1 (fully pressed)
Matches any controller id with the word gamecube
in it, or product id 0337
.
B0 = A (mapped as mainAction)
B1 = X
B2 = Y (mapped as altAction)
B3 = B (mapped as back)
B4 = LT // gets "pressed" as when the trigger is fully pressed
B5 = RT // gets "pressed" as when the trigger is fully pressed
B6 = Z
B7 = Start
B8 = Dpad Up (mapped as padUp)
B9 = Dpad Down (mapped as padDown)
B10 = Dpad Left (mapped as padLeft)
B11 = Dpad Right (mapped as padRight)
AXIS 0 = leftAxisX (mapped as leftStickLeft and leftStickRight) // -1 = left, 1 = right
AXIS 1 = leftAxisY (mapped as leftStickUp and leftStickDown) // -1 = up, 1 = down
AXIX 2 = LT // reports LT pressed value between -1 (not pressed) and 1 (fully pressed)
AXIS 3 = rightAxisX // -1 = left, 1 = right
AXIS 4 = rightAxisY (mapped as rightStickUp and rightStickDown) // -1 = up, 1 = down
AXIX 5 = RT // reports RT pressed value between -1 (not pressed) and 1 (fully pressed)
Layouts are defined in the src/helper/gamepad.ts
file. For a layout definition we need the following information from https://gamepad-tester.com:
- Controller ID: name of the controller as reported by the browser
- A list of all the
BX
andAXIS X
elements and the corresponding button/stick/trigger in the real controller - Also, you should specify which buttons should map to the valid interactions (mainAction, back, etc)
Layouts can be added to that file by defining a new function the checkActionsForXbox
and checkActionsForPlaystation
function or a new issue can be created with all the required information and we can add that.
If the layout corresponds to one of the already defined layouts, report that specifying the controller ID as shown in https://gamepad-tester.com
- Home
- Troubleshooting
- Getting Started with Heroic
- Platforms
- Game Fixes
- Contributing
- Custom Themes
- Trivia