mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-17 13:18:03 +08:00
Merge branch 'develop' into develop
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
## [next]
|
||||
|
||||
## 0.17.0
|
||||
- Fixing FlareAnimation API to match convention
|
||||
- Fixing FlareComponent renderization
|
||||
- Added default render fucntion for Box2D ChainShape
|
||||
- New GestureDetector API to Game
|
||||
|
||||
## 0.16.1
|
||||
- Added `Bgm` class for easy looping background music management.
|
||||
|
||||
6
FAQ.md
6
FAQ.md
@@ -52,6 +52,12 @@ If you are using `BaseGame`, you have a `camera` attribute that allows you to of
|
||||
|
||||
For a more in-depth tutorial on how the camera works (in general & in Flame) and how to use it, check [erickzanardo](https://github.com/erickzanardo)'s [excellent tutorial](https://fireslime.xyz/articles/20190911_Basic_Camera_Usage_In_Flame.html), published via FireSlime.
|
||||
|
||||
## How to handle touch events on your game?
|
||||
|
||||
You can always use all the Widgets and features that Flutter already provide for that, but Flame wraps gesture detector callbacks on its base Game class so it can ben a little easier to handle those events, you can find more about it on the input documentation page:
|
||||
|
||||
https://flame-engine.org/docs/input.md
|
||||
|
||||
## Other questions?
|
||||
|
||||
Didn't find what you needed here? Please head to [FireSlime's Discord channel](https://discord.gg/pxrBmy4) where the community might help you with more questions.
|
||||
|
||||
27
README.md
27
README.md
@@ -63,7 +63,7 @@ Just drop it in your `pubspec.yaml`:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
flame: ^0.16.1
|
||||
flame: ^0.17.0
|
||||
```
|
||||
|
||||
And start using it!
|
||||
@@ -263,21 +263,26 @@ A very simple `BaseGame` implementation example can be seen below:
|
||||
|
||||
### Input
|
||||
|
||||
In order to handle user input, you can use the libraries provided by Flutter for regular apps: [Gesture Recognizers](https://flutter.io/gestures/).
|
||||
Inside `package:flame/gestures.dart` you can find a whole set of `mixin` which can be included on your game class instance to be able to receive touch input events
|
||||
|
||||
However, in order to bind them, use the `Flame.util.addGestureRecognizer` method; in doing so, you'll make sure they are properly unbound when the game widget is not being rendered, and so the rest of your screens will work appropriately.
|
||||
|
||||
For example, to add a tap listener ("on click"):
|
||||
__Example__
|
||||
|
||||
```dart
|
||||
Flame.util.addGestureRecognizer(new TapGestureRecognizer()
|
||||
..onTapDown = (TapDownDetails evt) => game.handleInput(evt.globalPosition.dx, evt.globalPosition.dy));
|
||||
class MyGame extends Game with TapDetector {
|
||||
// Other methods ommited
|
||||
|
||||
@override
|
||||
void onTapDown(TapDownDetails details) {
|
||||
print("Player tap down on ${details.globalPosition.dx} - ${details.globalPosition.dy}");
|
||||
}
|
||||
|
||||
@override
|
||||
void onTapUp(TapUpDetails details) {
|
||||
print("Player tap up on ${details.globalPosition.dx} - ${details.globalPosition.dy}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Where `game` is a reference to your game object and `handleInput` is a method you create to handle the input inside your game.
|
||||
|
||||
If your game doesn't have other screens, just call this after your `runApp` call, in the `main` method.
|
||||
|
||||
[Complete Input Guide](doc/input.md)
|
||||
|
||||
## Credits
|
||||
|
||||
@@ -31,7 +31,7 @@ Put the pub package as your dependency by dropping the following in your `pubspe
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
flame: ^0.16.1
|
||||
flame: ^0.17.0
|
||||
```
|
||||
|
||||
And start using it!
|
||||
|
||||
72
doc/examples/gestures/.gitignore
vendored
Normal file
72
doc/examples/gestures/.gitignore
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Android related
|
||||
**/android/**/gradle-wrapper.jar
|
||||
**/android/.gradle
|
||||
**/android/captures/
|
||||
**/android/gradlew
|
||||
**/android/gradlew.bat
|
||||
**/android/local.properties
|
||||
**/android/**/GeneratedPluginRegistrant.java
|
||||
|
||||
# iOS/XCode related
|
||||
**/ios/**/*.mode1v3
|
||||
**/ios/**/*.mode2v3
|
||||
**/ios/**/*.moved-aside
|
||||
**/ios/**/*.pbxuser
|
||||
**/ios/**/*.perspectivev3
|
||||
**/ios/**/*sync/
|
||||
**/ios/**/.sconsign.dblite
|
||||
**/ios/**/.tags*
|
||||
**/ios/**/.vagrant/
|
||||
**/ios/**/DerivedData/
|
||||
**/ios/**/Icon?
|
||||
**/ios/**/Pods/
|
||||
**/ios/**/.symlinks/
|
||||
**/ios/**/profile
|
||||
**/ios/**/xcuserdata
|
||||
**/ios/.generated/
|
||||
**/ios/Flutter/App.framework
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/app.flx
|
||||
**/ios/Flutter/app.zip
|
||||
**/ios/Flutter/flutter_assets/
|
||||
**/ios/ServiceDefinitions.json
|
||||
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!**/ios/**/default.mode1v3
|
||||
!**/ios/**/default.mode2v3
|
||||
!**/ios/**/default.pbxuser
|
||||
!**/ios/**/default.perspectivev3
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
10
doc/examples/gestures/.metadata
Normal file
10
doc/examples/gestures/.metadata
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 841707365a9be08f2219cbafc52c52d6af5355aa
|
||||
channel: master
|
||||
|
||||
project_type: app
|
||||
3
doc/examples/gestures/README.md
Normal file
3
doc/examples/gestures/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# gestures
|
||||
|
||||
A flame game showcasing the use of gestures callbacks
|
||||
45
doc/examples/gestures/lib/main.dart
Normal file
45
doc/examples/gestures/lib/main.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame/gestures.dart';
|
||||
|
||||
void main() {
|
||||
final game = MyGame();
|
||||
runApp(game.widget);
|
||||
}
|
||||
|
||||
class MyGame extends Game with TapDetector, DoubleTapDetector, PanDetector {
|
||||
final _whitePaint = Paint()..color = const Color(0xFFFFFFFF);
|
||||
final _bluePaint = Paint()..color = const Color(0xFF0000FF);
|
||||
final _greenPaint = Paint()..color = const Color(0xFF00FF00);
|
||||
|
||||
Paint _paint;
|
||||
|
||||
Rect _rect = const Rect.fromLTWH(50, 50, 50, 50);
|
||||
|
||||
MyGame() {
|
||||
_paint = _whitePaint;
|
||||
}
|
||||
|
||||
@override
|
||||
void onTap() {
|
||||
_paint = _paint == _whitePaint ? _bluePaint : _whitePaint;
|
||||
}
|
||||
|
||||
@override
|
||||
void onDoubleTap() {
|
||||
_paint = _greenPaint;
|
||||
}
|
||||
|
||||
@override
|
||||
void onPanUpdate(DragUpdateDetails details) {
|
||||
_rect = _rect.translate(details.delta.dx, details.delta.dy);
|
||||
}
|
||||
|
||||
@override
|
||||
void update(double dt) {}
|
||||
|
||||
@override
|
||||
void render(Canvas canvas) {
|
||||
canvas.drawRect(_rect, _paint);
|
||||
}
|
||||
}
|
||||
16
doc/examples/gestures/pubspec.yaml
Normal file
16
doc/examples/gestures/pubspec.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
name: gestures
|
||||
description: A flame game showcasing the use of gestures callbacks
|
||||
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.1.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flame:
|
||||
path: ../../../
|
||||
|
||||
flutter:
|
||||
uses-material-design: false
|
||||
93
doc/input.md
93
doc/input.md
@@ -1,41 +1,84 @@
|
||||
# Input
|
||||
|
||||
In order to handle user input, you can use the libraries provided by Flutter for regular apps: [Gesture Recognizers](https://flutter.io/gestures/).
|
||||
|
||||
However, in order to bind them, use the `Flame.util.addGestureRecognizer` method; in doing so, you'll make sure they are properly unbound when the game widget is not being rendered, and so the rest of your screens will work appropriately.
|
||||
|
||||
For example, to add a tap listener ("on click"):
|
||||
Inside `package:flame/gestures.dart` you can find a whole set of `mixin` which can be included on your game class instance to be able to receive touch input events. Bellow you can see the full list of these `mixin`s and its methods:
|
||||
|
||||
```dart
|
||||
Flame.util.addGestureRecognizer(new TapGestureRecognizer()
|
||||
..onTapDown = (TapDownDetails evt) => game.handleInput(evt.globalPosition.dx, evt.globalPosition.dy));
|
||||
- TapDetector
|
||||
- onTap
|
||||
- onTapCancel
|
||||
- onTapDown
|
||||
- onTapUp
|
||||
|
||||
- SecondaryTapDetector
|
||||
- onSecondaryTapDown
|
||||
- onSecondaryTapUp
|
||||
- onSecondaryTapCancel
|
||||
|
||||
- DoubleTapDetector
|
||||
- onDoubleTap
|
||||
|
||||
- LongPressDetector
|
||||
- onLongPress
|
||||
- onLongPressStart
|
||||
- onLongPressMoveUpdate
|
||||
- onLongPressUp
|
||||
- onLongPressEnd
|
||||
|
||||
- VerticalDragDetector
|
||||
- onVerticalDragDown
|
||||
- onVerticalDragStart
|
||||
- onVerticalDragUpdate
|
||||
- onVerticalDragEnd
|
||||
- onVerticalDragCancel
|
||||
|
||||
- HorizontalDragDetector
|
||||
- onHorizontalDragDown
|
||||
- onHorizontalDragStart
|
||||
- onHorizontalDragUpdate
|
||||
- onHorizontalDragEnd
|
||||
- onHorizontalDragCancel
|
||||
|
||||
- ForcePressDetector
|
||||
- onForcePressStart
|
||||
- onForcePressPeak
|
||||
- onForcePressUpdate
|
||||
- onForcePressEnd
|
||||
|
||||
- PanDetector
|
||||
- onPanDown
|
||||
- onPanStart
|
||||
- onPanUpdate
|
||||
- onPanEnd
|
||||
- onPanCancel
|
||||
|
||||
- ScaleDetector
|
||||
- onScaleStart
|
||||
- onScaleUpdate
|
||||
- onScaleEnd
|
||||
```
|
||||
|
||||
Where `game` is a reference to your game object and `handleInput` is a method you create to handle the input inside your game.
|
||||
Many of these detectors can conflict with each other, for example, you can't register both Vertical and Horizontal drags, so not all of then can be used together.
|
||||
|
||||
If your game doesn't have other screens, just call this after your `runApp` call, in the `main` method.
|
||||
All of these methods are basically a mirror from the callbacks available on the [GestureDetector widget](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html), you can also read more about Flutter's gestures [here](https://api.flutter.dev/flutter/gestures/gestures-library.html).
|
||||
|
||||
Here are some example of more complex Gesture Recognizers:
|
||||
## Example
|
||||
|
||||
```dart
|
||||
MyGame() {
|
||||
// other init...
|
||||
class MyGame extends Game with TapDetector {
|
||||
// Other methods ommited
|
||||
|
||||
Flame.util.addGestureRecognizer(createDragRecognizer());
|
||||
Flame.util.addGestureRecognizer(createTapRecognizer());
|
||||
}
|
||||
@override
|
||||
void onTapDown(TapDownDetails details) {
|
||||
print("Player tap down on ${details.globalPosition.dx} - ${details.globalPosition.dy}");
|
||||
}
|
||||
|
||||
GestureRecognizer createDragRecognizer() {
|
||||
return new ImmediateMultiDragGestureRecognizer()
|
||||
..onStart = (Offset position) => this.handleDrag(position);
|
||||
}
|
||||
|
||||
TapGestureRecognizer createTapRecognizer() {
|
||||
return new TapGestureRecognizer()
|
||||
..onTapUp = (TapUpDetails details) => this.handleTap(details.globalPosition);;
|
||||
}
|
||||
@override
|
||||
void onTapUp(TapUpDetails details) {
|
||||
print("Player tap up on ${details.globalPosition.dx} - ${details.globalPosition.dy}");
|
||||
}
|
||||
}
|
||||
```
|
||||
__ATTENTION:__ `Flame.util.addGestureRecognizer` must be called after the `runApp`, otherwise Flutter's `GestureBinding` will not be initialized yet and exceptions will occur.
|
||||
You can also check a more complete example [here](/doc/examples/gestures).
|
||||
|
||||
## Tapable components
|
||||
|
||||
|
||||
26
doc/util.md
26
doc/util.md
@@ -55,11 +55,14 @@ Flame provides a simple utility class to help you handle countdowns and event li
|
||||
__Countdown example:__
|
||||
|
||||
```dart
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame/time.dart';
|
||||
import 'package:flame/text_config.dart';
|
||||
import 'dart:ui';
|
||||
|
||||
class MyGame extends MyGame {
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame/position.dart';
|
||||
import 'package:flame/text_config.dart';
|
||||
import 'package:flame/time.dart';
|
||||
|
||||
class MyGame extends Game {
|
||||
final TextConfig textConfig = TextConfig(color: const Color(0xFFFFFFFF));
|
||||
final countdown = Timer(2);
|
||||
|
||||
@@ -77,7 +80,8 @@ class MyGame extends MyGame {
|
||||
|
||||
@override
|
||||
void render(Canvas canvas) {
|
||||
textConfig.render(canvas, "Countdown: ${countdown.current.toString()}", Position(10, 100));
|
||||
textConfig.render(canvas, "Countdown: ${countdown.current.toString()}",
|
||||
Position(10, 100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +90,14 @@ class MyGame extends MyGame {
|
||||
__Interval example:__
|
||||
|
||||
```dart
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame/time.dart';
|
||||
import 'package:flame/text_config.dart';
|
||||
import 'dart:ui';
|
||||
|
||||
class MyGame extends MyGame {
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame/position.dart';
|
||||
import 'package:flame/text_config.dart';
|
||||
import 'package:flame/time.dart';
|
||||
|
||||
class MyGame extends Game {
|
||||
final TextConfig textConfig = TextConfig(color: const Color(0xFFFFFFFF));
|
||||
Timer interval;
|
||||
|
||||
@@ -105,6 +112,7 @@ class MyGame extends MyGame {
|
||||
|
||||
@override
|
||||
void update(double dt) {
|
||||
interval.update(dt);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
185
lib/game.dart
185
lib/game.dart
@@ -12,31 +12,14 @@ import 'package:ordered_set/ordered_set.dart';
|
||||
import 'components/component.dart';
|
||||
import 'components/mixins/has_game_ref.dart';
|
||||
import 'components/mixins/tapable.dart';
|
||||
import 'flame.dart';
|
||||
import 'position.dart';
|
||||
import 'gestures.dart';
|
||||
|
||||
/// Represents a generic game.
|
||||
///
|
||||
/// Subclass this to implement the [update] and [render] methods.
|
||||
/// Flame will deal with calling these methods properly when the game's widget is rendered.
|
||||
abstract class Game {
|
||||
TapGestureRecognizer _createTapGestureRecognizer() => TapGestureRecognizer()
|
||||
..onTapUp = (TapUpDetails details) {
|
||||
onTapUp(details);
|
||||
}
|
||||
..onTapDown = (TapDownDetails details) {
|
||||
onTapDown(details);
|
||||
}
|
||||
..onTapCancel = () {
|
||||
onTapCancel();
|
||||
};
|
||||
|
||||
void onTapCancel() {}
|
||||
void onTapDown(TapDownDetails details) {}
|
||||
void onTapUp(TapUpDetails details) {}
|
||||
|
||||
TapGestureRecognizer _gestureRecognizer;
|
||||
|
||||
// Widget Builder for this Game
|
||||
final builder = WidgetBuilder();
|
||||
|
||||
@@ -67,26 +50,162 @@ abstract class Game {
|
||||
Widget get widget => builder.build(this);
|
||||
|
||||
// Called when the Game widget is attached
|
||||
void onAttach() {
|
||||
if (_gestureRecognizer != null) {
|
||||
Flame.util.removeGestureRecognizer(_gestureRecognizer);
|
||||
}
|
||||
_gestureRecognizer = _createTapGestureRecognizer();
|
||||
Flame.util.addGestureRecognizer(_gestureRecognizer);
|
||||
}
|
||||
void onAttach() {}
|
||||
|
||||
// Called when the Game widget is detached
|
||||
void onDetach() {
|
||||
if (_gestureRecognizer != null) {
|
||||
Flame.util.removeGestureRecognizer(_gestureRecognizer);
|
||||
}
|
||||
}
|
||||
void onDetach() {}
|
||||
}
|
||||
|
||||
class WidgetBuilder {
|
||||
Offset offset = Offset.zero;
|
||||
Widget build(Game game) => Directionality(
|
||||
textDirection: TextDirection.ltr, child: EmbeddedGameWidget(game));
|
||||
|
||||
Widget build(Game game) {
|
||||
return GestureDetector(
|
||||
// Taps
|
||||
onTap: game is TapDetector ? () => (game as TapDetector).onTap() : null,
|
||||
onTapCancel: game is TapDetector
|
||||
? () => (game as TapDetector).onTapCancel()
|
||||
: null,
|
||||
onTapDown: game is TapDetector
|
||||
? (TapDownDetails d) => (game as TapDetector).onTapDown(d)
|
||||
: null,
|
||||
onTapUp: game is TapDetector
|
||||
? (TapUpDetails d) => (game as TapDetector).onTapUp(d)
|
||||
: null,
|
||||
|
||||
// Secondary taps
|
||||
onSecondaryTapDown: game is SecondaryTapDetector
|
||||
? (TapDownDetails d) =>
|
||||
(game as SecondaryTapDetector).onSecondaryTapDown(d)
|
||||
: null,
|
||||
onSecondaryTapUp: game is SecondaryTapDetector
|
||||
? (TapUpDetails d) =>
|
||||
(game as SecondaryTapDetector).onSecondaryTapUp(d)
|
||||
: null,
|
||||
onSecondaryTapCancel: game is SecondaryTapDetector
|
||||
? () => (game as SecondaryTapDetector).onSecondaryTapCancel()
|
||||
: null,
|
||||
|
||||
// Double tap
|
||||
onDoubleTap: game is DoubleTapDetector
|
||||
? () => (game as DoubleTapDetector).onDoubleTap()
|
||||
: null,
|
||||
|
||||
// Long presses
|
||||
onLongPress: game is LongPressDetector
|
||||
? () => (game as LongPressDetector).onLongPress()
|
||||
: null,
|
||||
onLongPressStart: game is LongPressDetector
|
||||
? (LongPressStartDetails d) =>
|
||||
(game as LongPressDetector).onLongPressStart(d)
|
||||
: null,
|
||||
onLongPressMoveUpdate: game is LongPressDetector
|
||||
? (LongPressMoveUpdateDetails d) =>
|
||||
(game as LongPressDetector).onLongPressMoveUpdate(d)
|
||||
: null,
|
||||
onLongPressUp: game is LongPressDetector
|
||||
? () => (game as LongPressDetector).onLongPressUp()
|
||||
: null,
|
||||
onLongPressEnd: game is LongPressDetector
|
||||
? (LongPressEndDetails d) =>
|
||||
(game as LongPressDetector).onLongPressEnd(d)
|
||||
: null,
|
||||
|
||||
// Vertical drag
|
||||
onVerticalDragDown: game is VerticalDragDetector
|
||||
? (DragDownDetails d) =>
|
||||
(game as VerticalDragDetector).onVerticalDragDown(d)
|
||||
: null,
|
||||
onVerticalDragStart: game is VerticalDragDetector
|
||||
? (DragStartDetails d) =>
|
||||
(game as VerticalDragDetector).onVerticalDragStart(d)
|
||||
: null,
|
||||
onVerticalDragUpdate: game is VerticalDragDetector
|
||||
? (DragUpdateDetails d) =>
|
||||
(game as VerticalDragDetector).onVerticalDragUpdate(d)
|
||||
: null,
|
||||
onVerticalDragEnd: game is VerticalDragDetector
|
||||
? (DragEndDetails d) =>
|
||||
(game as VerticalDragDetector).onVerticalDragEnd(d)
|
||||
: null,
|
||||
onVerticalDragCancel: game is VerticalDragDetector
|
||||
? () => (game as VerticalDragDetector).onVerticalDragCancel()
|
||||
: null,
|
||||
|
||||
// Horizontal drag
|
||||
onHorizontalDragDown: game is HorizontalDragDetector
|
||||
? (DragDownDetails d) =>
|
||||
(game as HorizontalDragDetector).onHorizontalDragDown(d)
|
||||
: null,
|
||||
onHorizontalDragStart: game is HorizontalDragDetector
|
||||
? (DragStartDetails d) =>
|
||||
(game as HorizontalDragDetector).onHorizontalDragStart(d)
|
||||
: null,
|
||||
onHorizontalDragUpdate: game is HorizontalDragDetector
|
||||
? (DragUpdateDetails d) =>
|
||||
(game as HorizontalDragDetector).onHorizontalDragUpdate(d)
|
||||
: null,
|
||||
onHorizontalDragEnd: game is HorizontalDragDetector
|
||||
? (DragEndDetails d) =>
|
||||
(game as HorizontalDragDetector).onHorizontalDragEnd(d)
|
||||
: null,
|
||||
onHorizontalDragCancel: game is HorizontalDragDetector
|
||||
? () => (game as HorizontalDragDetector).onHorizontalDragCancel()
|
||||
: null,
|
||||
|
||||
// Force presses
|
||||
onForcePressStart: game is ForcePressDetector
|
||||
? (ForcePressDetails d) =>
|
||||
(game as ForcePressDetector).onForcePressStart(d)
|
||||
: null,
|
||||
onForcePressPeak: game is ForcePressDetector
|
||||
? (ForcePressDetails d) =>
|
||||
(game as ForcePressDetector).onForcePressPeak(d)
|
||||
: null,
|
||||
onForcePressUpdate: game is ForcePressDetector
|
||||
? (ForcePressDetails d) =>
|
||||
(game as ForcePressDetector).onForcePressUpdate(d)
|
||||
: null,
|
||||
onForcePressEnd: game is ForcePressDetector
|
||||
? (ForcePressDetails d) =>
|
||||
(game as ForcePressDetector).onForcePressEnd(d)
|
||||
: null,
|
||||
|
||||
// Pan
|
||||
onPanDown: game is PanDetector
|
||||
? (DragDownDetails d) => (game as PanDetector).onPanDown(d)
|
||||
: null,
|
||||
onPanStart: game is PanDetector
|
||||
? (DragStartDetails d) => (game as PanDetector).onPanStart(d)
|
||||
: null,
|
||||
onPanUpdate: game is PanDetector
|
||||
? (DragUpdateDetails d) => (game as PanDetector).onPanUpdate(d)
|
||||
: null,
|
||||
onPanEnd: game is PanDetector
|
||||
? (DragEndDetails d) => (game as PanDetector).onPanEnd(d)
|
||||
: null,
|
||||
onPanCancel: game is PanDetector
|
||||
? () => (game as PanDetector).onPanCancel()
|
||||
: null,
|
||||
|
||||
// Scales
|
||||
onScaleStart: game is ScaleDetector
|
||||
? (ScaleStartDetails d) => (game as ScaleDetector).onScaleStart(d)
|
||||
: null,
|
||||
onScaleUpdate: game is ScaleDetector
|
||||
? (ScaleUpdateDetails d) => (game as ScaleDetector).onScaleUpdate(d)
|
||||
: null,
|
||||
onScaleEnd: game is ScaleDetector
|
||||
? (ScaleEndDetails d) => (game as ScaleDetector).onScaleEnd(d)
|
||||
: null,
|
||||
|
||||
child: Container(
|
||||
color: const Color(0xFF000000),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: EmbeddedGameWidget(game))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a more complete and opinionated implementation of Game.
|
||||
@@ -94,7 +213,7 @@ class WidgetBuilder {
|
||||
/// It still needs to be subclasses to add your game logic, but the [update], [render] and [resize] methods have default implementations.
|
||||
/// This is the recommended structure to use for most games.
|
||||
/// It is based on the Component system.
|
||||
abstract class BaseGame extends Game {
|
||||
abstract class BaseGame extends Game with TapDetector {
|
||||
/// The list of components to be updated and rendered by the base game.
|
||||
OrderedSet<Component> components =
|
||||
OrderedSet(Comparing.on((c) => c.priority()));
|
||||
|
||||
63
lib/gestures.dart
Normal file
63
lib/gestures.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
|
||||
mixin TapDetector {
|
||||
void onTap() {}
|
||||
void onTapCancel() {}
|
||||
void onTapDown(TapDownDetails details) {}
|
||||
void onTapUp(TapUpDetails details) {}
|
||||
}
|
||||
|
||||
mixin SecondaryTapDetector {
|
||||
void onSecondaryTapDown(TapDownDetails details) {}
|
||||
void onSecondaryTapUp(TapUpDetails details) {}
|
||||
void onSecondaryTapCancel() {}
|
||||
}
|
||||
|
||||
mixin DoubleTapDetector {
|
||||
void onDoubleTap() {}
|
||||
}
|
||||
|
||||
mixin LongPressDetector {
|
||||
void onLongPress() {}
|
||||
void onLongPressStart(LongPressStartDetails details) {}
|
||||
void onLongPressMoveUpdate(LongPressMoveUpdateDetails details) {}
|
||||
void onLongPressUp() {}
|
||||
void onLongPressEnd(LongPressEndDetails details) {}
|
||||
}
|
||||
|
||||
mixin VerticalDragDetector {
|
||||
void onVerticalDragDown(DragDownDetails details) {}
|
||||
void onVerticalDragStart(DragStartDetails details) {}
|
||||
void onVerticalDragUpdate(DragUpdateDetails details) {}
|
||||
void onVerticalDragEnd(DragEndDetails details) {}
|
||||
void onVerticalDragCancel() {}
|
||||
}
|
||||
|
||||
mixin HorizontalDragDetector {
|
||||
void onHorizontalDragDown(DragDownDetails details) {}
|
||||
void onHorizontalDragStart(DragStartDetails details) {}
|
||||
void onHorizontalDragUpdate(DragUpdateDetails details) {}
|
||||
void onHorizontalDragEnd(DragEndDetails details) {}
|
||||
void onHorizontalDragCancel() {}
|
||||
}
|
||||
|
||||
mixin ForcePressDetector {
|
||||
void onForcePressStart(ForcePressDetails details) {}
|
||||
void onForcePressPeak(ForcePressDetails details) {}
|
||||
void onForcePressUpdate(ForcePressDetails details) {}
|
||||
void onForcePressEnd(ForcePressDetails details) {}
|
||||
}
|
||||
|
||||
mixin PanDetector {
|
||||
void onPanDown(DragDownDetails details) {}
|
||||
void onPanStart(DragStartDetails details) {}
|
||||
void onPanUpdate(DragUpdateDetails details) {}
|
||||
void onPanEnd(DragEndDetails details) {}
|
||||
void onPanCancel() {}
|
||||
}
|
||||
|
||||
mixin ScaleDetector {
|
||||
void onScaleStart(ScaleStartDetails details) {}
|
||||
void onScaleUpdate(ScaleUpdateDetails details) {}
|
||||
void onScaleEnd(ScaleEndDetails details) {}
|
||||
}
|
||||
@@ -113,6 +113,10 @@ class Util {
|
||||
/// This properly binds a gesture recognizer to your game.
|
||||
///
|
||||
/// Use this in order to get it to work in case your app also contains other widgets.
|
||||
///
|
||||
/// Read more at: https://flame-engine.org/docs/input.md
|
||||
///
|
||||
/// @Deprecated('This method can lead to confuse behaviour, use the gestures methods provided by the Game class')
|
||||
void addGestureRecognizer(GestureRecognizer recognizer) {
|
||||
if (GestureBinding.instance == null) {
|
||||
throw Exception(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: flame
|
||||
description: A minimalist Flutter game engine, provides a nice set of somewhat independent modules you can choose from.
|
||||
version: 0.16.1
|
||||
version: 0.17.0
|
||||
author: Luan Nico <luannico27@gmail.com>
|
||||
homepage: https://github.com/flame-engine/flame
|
||||
|
||||
|
||||
Reference in New Issue
Block a user