Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/flame/collision_detection.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ other. For example, an arrow hitting an enemy or the player picking up a coin.

In most collision detection systems you use something called hitboxes to create more precise
bounding boxes of your components. In Flame the hitboxes are areas of the component that can react
to collisions and make [gesture input](inputs/gesture_input.md#gesturehitboxes) more accurate.
to collisions and make [gesture input](inputs/inputs.md#gesturehitboxes) more accurate.

The collision detection system supports three different types of shapes that you can build hitboxes
from, these shapes are Polygon, Rectangle and Circle. Multiple hitboxes can be added to a
Expand Down Expand Up @@ -226,7 +226,7 @@ and two `RectangleHitbox`s as its hat.

A hitbox can be used either for collision detection or for making gesture detection more accurate
on top of components, see more regarding the latter in the section about the
[GestureHitboxes](inputs/gesture_input.md#gesturehitboxes) mixin.
[GestureHitboxes](inputs/inputs.md#gesturehitboxes) mixin.


### CollisionType
Expand Down
32 changes: 4 additions & 28 deletions doc/flame/inputs/drag_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,31 +131,7 @@ It can be used, for example, to change the component's visual appearance during

## Combining with ScaleCallbacks

A component can use both `DragCallbacks` and `ScaleCallbacks` at the same time. When both mixins are
present, single-finger gestures produce drag events and two-finger gestures produce both drag and
scale events. This is useful for components that should be draggable with one finger and
pinch-to-zoom or rotatable with two fingers.

```dart
class InteractiveRectangle extends RectangleComponent
with ScaleCallbacks, DragCallbacks {

double _initialAngle = 0;

@override
void onDragUpdate(DragUpdateEvent event) {
position += event.localDelta;
}

@override
void onScaleStart(ScaleStartEvent event) {
super.onScaleStart(event);
_initialAngle = angle;
}

@override
void onScaleUpdate(ScaleUpdateEvent event) {
angle = _initialAngle + event.rotation;
}
}
```
`DragCallbacks` and `ScaleCallbacks` can be used at the same time: single-finger gestures produce
drag events, and two-finger gestures produce both drag and scale events. See
[Combining with DragCallbacks](scale_events.md#combining-with-dragcallbacks) for how to make the two
work together, both on a component and for panning and zooming the camera.
146 changes: 0 additions & 146 deletions doc/flame/inputs/gesture_input.md

This file was deleted.

80 changes: 58 additions & 22 deletions doc/flame/inputs/inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,70 @@

Games are interactive by nature, so handling player input is essential. Flame provides input
handling that works on all platforms Flutter supports: touch on mobile, mouse and keyboard on
desktop, and
pointer events on the web. These APIs are designed as mixins that you add to your components, so
each component can independently decide which input events it cares about. This is similar to how
desktop, and pointer events on the web. These APIs are designed as mixins that you add to your
components, so each component can independently decide which input events it cares about. This is
similar to how
Flutter's [GestureDetector](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html)
works, but adapted for Flame's component tree.

- [Tap Events](tap_events.md)
- [Drag Events](drag_events.md)
- [Scale Events](scale_events.md)
- [Long Press Events](long_press_events.md)
- [Gesture Input](gesture_input.md)
- [Keyboard Input](keyboard_input.md)
- [Other Inputs and Helpers](other_inputs.md)
- [Pointer Events](pointer_events.md)
Since `FlameGame` is itself a `Component`, adding one of these mixins to your game class works
exactly as well as adding it to a component; no wrapper component required.

- [Tap Events](tap_events.md): `TapCallbacks`, `SecondaryTapCallbacks`, `TertiaryTapCallbacks`,
`DoubleTapCallbacks`
- [Drag Events](drag_events.md): `DragCallbacks`
- [Scale Events](scale_events.md): `ScaleCallbacks`
- [Long Press Events](long_press_events.md): `LongPressCallbacks`
- [Pointer Events](pointer_events.md): `MouseMoveCallbacks`, `HoverCallbacks`, `ScrollCallbacks`
- [Keyboard Input](keyboard_input.md): for keystrokes
- [Hardware Keyboard Detector](hardware_keyboard_detector.md)
- [Other Inputs and Helpers](other_inputs.md): for joysticks, game pads, etc.

Under the hood, these are all built on Flutter's own gesture widgets, including the
[GestureDetector widget](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html),
[RawGestureDetector widget](https://api.flutter.dev/flutter/widgets/RawGestureDetector-class.html)
and [MouseRegion widget](https://api.flutter.dev/flutter/widgets/MouseRegion-class.html); you can
also read more about
[Flutter's gesture system](https://api.flutter.dev/flutter/gestures/gestures-library.html).


## Event coordinate system

Every event that carries a position reports it in three coordinate systems:

- `devicePosition`: relative to the entire screen, the same as `globalPosition` in Flutter's native
events.
- `canvasPosition`: relative to the `GameWidget` position and size, the same as `localPosition` in
Flutter's native events. This is Flame's "global" position.
- `localPosition`: relative to the component currently receiving the event, with the whole chain of
parent transforms (camera included) already applied.

Events that represent a movement, such as `DragUpdateEvent`, additionally expose start and end
positions (`canvasStartPosition` / `canvasEndPosition`, and so on) plus the corresponding deltas:
`deviceDelta`, `canvasDelta` and `localDelta`.

`localPosition` and `localDelta` are relative to whichever component is currently receiving the
event, so only read them inside the callback. Do not hold on to the event and read them afterwards:
once delivery is over they are no longer maintained, and depending on the event you will either get
a leftover value or an error. If you need the position later, copy it during the callback with
`event.localPosition.clone()`.

When you mix a callback into your `FlameGame` directly, the game is that component; and since it has
no transform of its own, the local values there are equivalent to the canvas coordinates.


## GestureHitboxes

Every mixin whose events carry a position implements `PointerInputCallbacks` — that is all of the
above except keyboard — and they all decide whether an event belongs to a component by asking its
`containsLocalPoint()`, which for a `PositionComponent` is its rectangular bounds. The
`GestureHitboxes` mixin is used to recognize input on top of your `Component`s more accurately than
that. Say that you have a fairly round rock as a `SpriteComponent` for example, then you don't want
to register input that is in the corner of the image where the rock is not displayed. Then you can
use the `GestureHitboxes` mixin to define a more accurate circle or polygon (or another shape) for
which the input should be within for the event to be registered on your component.
Every mixin whose events carry a position implements `PointerInputCallbacks` (taps, drags, scales,
long presses and pointer events - but not the keyboard ones) and they all decide whether an event
belongs to a component by asking its `containsLocalPoint()`, which for a `PositionComponent` is its
rectangular bounds.

The `GestureHitboxes` mixin is used to recognize input on top of your `Component`s more accurately.
Say that you have a round rock as a `SpriteComponent` for example, then you don't want to register
input that is in the corner of the image where the rock is not displayed; you can use the
`GestureHitboxes` mixin to define a more accurate boundary (circle, polygon, any shape) for the
event to check when propagating to your component.

You can add new hitboxes to the component that has the `GestureHitboxes` mixin just like they are
added in the `Collidable` example.
Expand All @@ -46,9 +83,8 @@ Tap Events <tap_events.md>
Drag Events <drag_events.md>
Scale Events <scale_events.md>
Long Press Events <long_press_events.md>
Gesture Input <gesture_input.md>
Keyboard Input <keyboard_input.md>
Other Inputs <other_inputs.md>
Pointer Events <pointer_events.md>
Keyboard Input <keyboard_input.md>
HardwareKeyboardDetector <hardware_keyboard_detector.md>
Other Inputs <other_inputs.md>
```
5 changes: 0 additions & 5 deletions doc/flame/inputs/keyboard_input.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@

This includes documentation for keyboard inputs.

For other input documents, see also:

- [Gesture Input](gesture_input.md): for mouse and touch pointer gestures
- [Other Inputs](other_inputs.md): For joysticks, game pads, etc.


## Intro

Expand Down
5 changes: 0 additions & 5 deletions doc/flame/inputs/other_inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@

This includes documentation for input methods besides keyboard and mouse.

For other input documents, see also:

- [Gesture Input](gesture_input.md): for mouse and touch pointer gestures
- [Keyboard Input](keyboard_input.md): for keystrokes


## Joystick

Expand Down
31 changes: 22 additions & 9 deletions doc/flame/inputs/pointer_events.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Pointer Events

```{note}
This document describes the new events API. The old (legacy) approach,
which is still supported, is described in [](gesture_input.md).
```

**Pointer events** are Flutter's generalized "mouse-movement"-type events (for desktop or web).

If you want to interact with mouse movement events within your component or game, you can use the
Expand Down Expand Up @@ -86,8 +81,7 @@ Play with the demo below to see the pointer hover events in action.

## ScrollCallbacks

If you want to handle mouse-wheel or trackpad scroll events at the component level, use the
`ScrollCallbacks` mixin.
If you want to handle mouse-wheel or trackpad scroll events, use the `ScrollCallbacks` mixin.

```dart
class ScrollableSquare extends RectangleComponent with ScrollCallbacks {
Expand Down Expand Up @@ -119,8 +113,8 @@ The `ScrollEvent` provides:
Scroll events are delivered to **all** components under the pointer (not just the topmost one),
unless set `continuePropagation = false` is set to stop it from bubbling further.

You can also mix `ScrollCallbacks` directly into your `FlameGame` to handle scrolling at the
game level.
You can also mix `ScrollCallbacks` directly into your `FlameGame` to handle scrolling anywhere on
the game surface.


### Scroll Demo
Expand All @@ -130,3 +124,22 @@ game level.
:page: scroll
:show: widget code
```


## Mouse cursor

It is also possible to change the current mouse cursor displayed on the `GameWidget` region. To do
so the following code can be used inside the `Game` class

```dart
mouseCursor.value = SystemMouseCursors.move;
```

To initialize the `GameWidget` with a custom cursor immediately, the `mouseCursor` property can be used:

```dart
GameWidget(
game: MouseCursorGame(),
mouseCursor: SystemMouseCursors.move,
);
```
Loading
Loading