Keyboard Input¶
This includes documentation for keyboard inputs.
For other input documents, see also:
Gesture Input: for mouse and touch pointer gestures
Other Inputs: For joysticks, game pads, etc.
Intro¶
The keyboard API on flame relies on the Flutter’s Focus widget.
To customize focus behavior, see Controlling focus.
There are two ways a game can react to key strokes; at the game level and at a component level.
For each we have a mixin that can me added to a Game
or Component
class.
Receive keyboard events in a game level¶
To make a Game
sub class sensitive to key stroke, mix it with KeyboardEvents
.
After that, it will be possible to override an onKeyEvent
method.
This method receives two parameters, first the
KeyEvent
that triggers the callback in the first place. The second is a set of the currently pressed
LogicalKeyboardKey
.
The return value is a
KeyEventResult
.
KeyEventResult.handled
will tell the framework that the key stroke was resolved inside of Flame
and skip any other keyboard handler widgets apart of GameWidget
.
KeyEventResult.ignored
will tell the framework to keep testing this event in any other keyboard
handler widget apart of GameWidget
. If the event is not resolved by any handler, the framework
will trigger SystemSoundType.alert
.
KeyEventResult.skipRemainingHandlers
is very similar to .ignored
, apart from the fact that will
skip any other handler widget and will straight up play the alert sound.
Minimal example:
class MyGame extends FlameGame with KeyboardEvents {
// ...
@override
KeyEventResult onKeyEvent(
KeyEvent event,
Set<LogicalKeyboardKey> keysPressed,
) {
final isKeyDown = event is KeyDownEvent;
final isSpace = keysPressed.contains(LogicalKeyboardKey.space);
if (isSpace && isKeyDown) {
if (keysPressed.contains(LogicalKeyboardKey.altLeft) ||
keysPressed.contains(LogicalKeyboardKey.altRight)) {
this.shootHarder();
} else {
this.shoot();
}
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
}
}
Receive keyboard events in a component level¶
To receive keyboard events directly in components, there is the mixin KeyboardHandler
.
Similarly to TapCallbacks
and DragCallbacks
, KeyboardHandler
can be mixed into any subclass of
Component
.
KeyboardHandlers must only be added to games that are mixed with HasKeyboardHandlerComponents
.
⚠️ Note: If
HasKeyboardHandlerComponents
is used, you must removeKeyboardEvents
from the game mixin list to avoid conflicts.
After applying KeyboardHandler
, it will be possible to override an onKeyEvent
method.
This method receives two parameters. First the
KeyEvent
that triggered the callback in the first place. The second is a set of the currently pressed
LogicalKeyboardKey
s.
The returned value should be true
to allow the continuous propagation of the key event among other
components. To not allow any other component to receive the event, return false
.
Flame also provides a default implementation called KeyboardListenerComponent
which can be used
to handle keyboard events. Like any other component, it can be added as a child to a FlameGame
or another Component
:
For example, imagine a PositionComponent
which has methods to move on the X and Y axis,
then the following code could be used to bind those methods to key events:
add(
KeyboardListenerComponent(
keyUp: {
LogicalKeyboardKey.keyA: (keysPressed) { ... },
LogicalKeyboardKey.keyD: (keysPressed) { ... },
LogicalKeyboardKey.keyW: (keysPressed) { ... },
LogicalKeyboardKey.keyS: (keysPressed) { ... },
},
keyDown: {
LogicalKeyboardKey.keyA: (keysPressed) { ... },
LogicalKeyboardKey.keyD: (keysPressed) { ... },
LogicalKeyboardKey.keyW: (keysPressed) { ... },
LogicalKeyboardKey.keyS: (keysPressed) { ... },
},
),
);
Controlling focus¶
On the widget level, it is possible to use the
FocusNode
API to control whether
the game is focused or not.
GameWidget
has an optional focusNode
parameter that allow its focus to be controlled externally.
By default GameWidget
has its autofocus
set to true, which means it will get focused once it is
mounted. To override that behavior, set autofocus
to false.
For a more complete example see here.