This adds `DisplacementEvent` to fix delta coordinate transformations
for drag events, to be used instead of `PositionEvent`.
Drag Events now expose the start and end position, as well as the delta,
correctly transformed by the camera and zoom.
This also ensures that drag events, once starts, do not get lost if the
drag update leaves the component bounds.
* if you are using `DragUpdateEvent` events, the `devicePosition`,
`canvasPosition`, `localPosition`, and `delta` are deprecated as they
are unclear.
* use `xStartPosition` to get the position at the start of the drag
event ("from")
* use `xEndPosition` to get the position at the end of the drag event
("to")
* if you want the delta, use `localDelta`. it now already considers the
camera zoom. no need to manually account for that
* now you keep receiving drag events for the same component even if the
mouse leaves the component (breaking)
---------
Co-authored-by: Lukas Klingsbo <lukas.klingsbo@gmail.com>
Primarily this PR is completing Step 5 of Flame's Klondike Tutorial and removing the tbc.md file ("To be continued...").
As at the end of Step 4, the Klondike Game had no animation, other than the drag-and-drop moves to play the game. It also had no ways to detect a win, react to a win or play again without re-loading and re-running the whole app. Step 4 played the Klondike Draw 3 variation of Klondike. Step 5 introduces the easier Klondike Draw 1 variation and provides buttons to:
Choose between Draw 1 and Draw 3,
Start the game again with a new deal, or
Start again with the same deal as before.
The new code and step5.md tutorial text cover Effects and EffectControllers in some detail, with complex examples of their use. The animations include:
Returning dropped but misplaced cards to the places they came from,
Settling dropped and validly placed cards into position,
Flipping cards from Stock Pile to Waste Pile,
Turning cards over on the Tableau piles when the cards above them are moved away,
Collecting multiple cards when the game is over,
Dealing and re-dealing multiple cards,
Allowing a card to be auto-moved onTapUp() to its Foundation Pile if it is ready to go out,
Providing a display of moving cards when/if the player wins.
Firstly, (re Issue #2799) Flame 1.9.x broke the Klondike Tutorial, which was not set up to use the new built-in world and camera. So I modified the KlondikeGame's onLoad() code to use the built-in world and camera and no longer create its own World and CameraComponent. I also updated the step2.md documentation file, which instructs new users of Flame on how to use the world and the camera, how to set up a game-oriented co-ordinate system and how to fit it into the device screen.
Secondly, (re Issue #2798) Klondike was not adhering to the design stated in the Tutorial, that all 52 Card objects would be owned by the KlondikeGame. During the shuffle and deal sequence it was using removeLast() on the List\<Card\>cards, where the cards are kept, the result being that only 24 of the 52 cards were left in the list after the deal. I have fixed the bug and updated the Tutorial documentation (step4) which discusses how the deal is coded.
This bug does not affect the gameplay as it stands, but it does block the way to future features at the game level, such as an option to re-deal or a win-animation where all cards fly off the screen.
I have just finished steps 1-4 of the Klondike tutorial and noticed a
couple of minor things that look to be outdated with the current dart /
flame versions.
### Step 3 - `late` keyword isn't required
When following this step the analyser hightlight this rule
[unnecessary_late](https://dart.dev/tools/linter-rules/unnecessary_late)
(introduced in Dart 2.16.0) which states:
> Top-level and static variables with initializers are already evaluated
lazily as if they are marked late.
I updated the notes around why the laziness is important so the reader
can still understand the reasoning.
It just removes a deprecated line that is in the tutorial for building a Klondike game. The final code does not have it and it is no longer necessary to have it in the KlondikeGame class.
This PR is first in a series of refactors that aim to simplify event handling in Flame. The approach is as follows:
Added class GestureDetectorBuilder, which encapsulates the logic of applyGestureDetectors() in a class. This class resides within the Game and initiates widget rebuild whenever any new gesture detectors are added or removed. Note:
[idea] Convert HasTappableComponents/HasDraggableComponents into classes #1733 suggests having a list of interfaces inside the Game class -- this is essentially that list, encapsulated in a class.
Added the MultiDragDispatcher component, which contains the logic that used to be within the HasDraggableComponents mixin. This component is internal; it mounts to a FlameGame directly, and ensures that it is a singleton.
Whenever any DragCallbacks component is added to a game, it automatically adds the MultiDragDispatcher component (unless there is already one), which in turn registers a drag gesture detector with GestureDetectorBuilder and rebuilds the game widget.
The end result is that now in order to make a component draggable you only need to add the DragCallbacks mixin to that component, everything else will be handled by the framework.
Consequently, the HasDraggableComponents mixin is now empty and marked as deprecated.