just_gamepads 0.1.0
just_gamepads: ^0.1.0 copied to clipboard
Gamepad input for Flutter on Android, iOS, macOS, Windows, Linux and the web (WASM too): Xbox, PlayStation, Nintendo and generic controllers in one standard layout.
Just Gamepads #
Gamepad input for Flutter on Android, iOS, macOS, Windows, Linux and the web, including WebAssembly builds. Xbox, PlayStation, Nintendo and generic controllers all report in one standard button and axis layout, so game code never deals with per-brand or per-platform differences.
Features #
- Every connected controller, with connect and disconnect events, ready for local multiplayer.
- Full-state snapshots per controller: no deltas to reassemble.
- One layout everywhere: the W3C Standard Gamepad buttons and axes, with sticks in -1..1 (Y down-positive) and triggers in 0..1.
mostRecentlyActiveId: the controller a player touched last, for single-player games. Stick drift on an idle controller doesn't count.- Controller families (Xbox, PlayStation, Nintendo, generic) for picking button glyphs.
Platform support #
| Platform | Backend | Notes |
|---|---|---|
| Android | Key and motion events | |
| iOS 13+ | GameController framework | Extended gamepads (Xbox, PlayStation, Switch Pro, MFi) |
| macOS 10.15+ | GameController framework | Extended gamepads (Xbox, PlayStation, Switch Pro, MFi) |
| Windows 10+ | Windows.Gaming.Input | Xbox controllers natively; others through RawGameController |
| Linux | evdev (/dev/input) |
No extra system libraries |
| Web (JS and WASM) | Browser Gamepad API | Controllers appear after a button press |
Getting started #
flutter pub add just_gamepads
import 'package:just_gamepads/just_gamepads.dart';
final pads = GamepadManager.instance;
pads.connections.listen((event) {
print('${event.info.name} (${event.info.type.name}) '
'${event.connected ? 'connected' : 'disconnected'}');
});
pads.stateChanges.listen((event) {
final state = event.state;
final jump = state.buttonsDown.contains(GamepadButton.a);
final moveX = state.axes[GamepadAxis.leftStickX] ?? 0.0;
// ...
});
await pads.start();
Subscribe before calling start() to receive the controllers that are
already connected as events; afterwards they are also listed in
pads.connected. The latest state of any controller is available from
pads.latestState(id) at any time.
Call pads.dispose() when the game shuts down.
The standard layout #
Face buttons are named by position, using Xbox letters: GamepadButton.a is
the bottom face button on every controller.
| Index | GamepadButton |
Xbox | PlayStation | Nintendo |
|---|---|---|---|---|
| 0 | a |
A | Cross | B |
| 1 | b |
B | Circle | A |
| 2 | x |
X | Square | Y |
| 3 | y |
Y | Triangle | X |
| 4 | leftBumper |
LB | L1 | L |
| 5 | rightBumper |
RB | R1 | R |
| 6 | leftTriggerButton |
LT | L2 | ZL |
| 7 | rightTriggerButton |
RT | R2 | ZR |
| 8 | back |
View | Share / Create | Minus |
| 9 | start |
Menu | Options | Plus |
| 10 | leftStick |
LS | L3 | Left stick |
| 11 | rightStick |
RS | R3 | Right stick |
| 12-15 | dpadUp, dpadDown, dpadLeft, dpadRight |
D-pad | D-pad | D-pad |
GamepadAxis |
Range |
|---|---|
leftStickX, rightStickX |
-1 (left) to 1 (right) |
leftStickY, rightStickY |
-1 (up) to 1 (down) |
leftTrigger, rightTrigger |
0 (released) to 1 (fully pressed) |
The trigger buttons are derived from the analog triggers past
triggerButtonThreshold (0.5) on platforms that only report an axis. Raw
stick values are passed through as reported: apply your own deadzone.
GamepadInfo.type gives the controller family for glyphs. It is
GamepadType.generic for controllers it can't identify.
Platform notes #
Web. Browsers expose a controller only after the user presses a button on
it while the page has focus. Both flutter build web and
flutter build web --wasm are supported.
Linux. The app reads /dev/input/event* directly. Desktop distributions
give the logged-in user access to game controllers; sandboxed apps (Flatpak,
Snap) need device access granted. Controllers without the kernel's standard
gamepad mapping are reported positionally, like on the other platforms'
fallback paths.
Windows. Xbox and XInput controllers are read through the Gamepad API; PlayStation, Switch and generic controllers through RawGameController. Windows may withhold controller input from apps that aren't in the foreground.
Android. Controller key events still reach Flutter as well, as
KeyEvents with LogicalKeyboardKey.gameButton* keys.
iOS and macOS. Controllers that only offer a micro gamepad profile (such as the Siri Remote) are not reported.
Testing #
GamepadManager accepts any GamepadBackend, so tests can drive it with a
fake instead of real hardware:
final manager = GamepadManager(backend: FakeBackend());
The example/ app is a live controller tester for checking a controller on
real hardware.
License #
BSD 3-Clause. See LICENSE.