diff --git a/packages/flame/example/lib/main.dart b/packages/flame/example/lib/main.dart index 1a77e65b49a..467cc948fec 100644 --- a/packages/flame/example/lib/main.dart +++ b/packages/flame/example/lib/main.dart @@ -14,7 +14,42 @@ void main() { ); } -class Square extends PositionComponent { +/// This example simply adds a rotating white square on the screen, if you press +/// somewhere other than on the existing square another square will be added and +/// if you press on a square it will be removed. +class MyGame extends FlameGame with DoubleTapDetector, HasTappables { + bool running = true; + + @override + Future onLoad() async { + await super.onLoad(); + add(Square(Vector2(100, 200))); + } + + @override + void onTapUp(int id, TapUpInfo info) { + super.onTapUp(id, info); + final touchPoint = info.eventPosition.game; + final handled = children.any((c) => c.shouldRemove); + + if (!handled) { + add(Square(touchPoint)); + } + } + + @override + void onDoubleTap() { + if (running) { + pauseEngine(); + } else { + resumeEngine(); + } + + running = !running; + } +} + +class Square extends PositionComponent with Tappable { static const speed = 0.25; static const squareSize = 128.0; @@ -22,6 +57,8 @@ class Square extends PositionComponent { static Paint red = BasicPalette.red.paint(); static Paint blue = BasicPalette.blue.paint(); + Square(Vector2 position) : super(position: position); + @override void render(Canvas c) { c.drawRect(size.toRect(), white); @@ -42,46 +79,10 @@ class Square extends PositionComponent { size.setValues(squareSize, squareSize); anchor = Anchor.center; } -} - -class MyGame extends FlameGame with DoubleTapDetector, TapDetector { - bool running = true; @override - Future onLoad() async { - await super.onLoad(); - add( - Square() - ..x = 100 - ..y = 100, - ); - } - - @override - void onTapUp(TapUpInfo info) { - final touchPoint = info.eventPosition.game; - - final handled = children.any((c) { - if (c is PositionComponent && c.containsPoint(touchPoint)) { - remove(c); - return true; - } - return false; - }); - - if (!handled) { - add(Square()..position = touchPoint); - } - } - - @override - void onDoubleTap() { - if (running) { - pauseEngine(); - } else { - resumeEngine(); - } - - running = !running; + bool onTapUp(TapUpInfo info) { + removeFromParent(); + return true; } } diff --git a/packages/flame/example/pubspec.yaml b/packages/flame/example/pubspec.yaml index 8fd9ebd57c7..4bce9fefeca 100644 --- a/packages/flame/example/pubspec.yaml +++ b/packages/flame/example/pubspec.yaml @@ -1,9 +1,7 @@ name: flame_example description: Simple example of a Flame game - -publish_to: 'none' - version: 0.1.0 +publish_to: 'none' environment: sdk: ">=2.14.0 <3.0.0" diff --git a/packages/flame/lib/src/components/mixins/tappable.dart b/packages/flame/lib/src/components/mixins/tappable.dart index 602582d9c72..488499ad128 100644 --- a/packages/flame/lib/src/components/mixins/tappable.dart +++ b/packages/flame/lib/src/components/mixins/tappable.dart @@ -61,6 +61,7 @@ mixin Tappable on Component { } } +// TODO(spydon): these methods should return the result of propagateToChildren. mixin HasTappables on FlameGame { @mustCallSuper void onTapCancel(int pointerId) { diff --git a/packages/flame/lib/src/game/game_widget/game_widget.dart b/packages/flame/lib/src/game/game_widget/game_widget.dart index a36c91e5593..b4ef623e6de 100644 --- a/packages/flame/lib/src/game/game_widget/game_widget.dart +++ b/packages/flame/lib/src/game/game_widget/game_widget.dart @@ -264,34 +264,33 @@ class _GameWidgetState extends State> { @override Widget build(BuildContext context) { - Widget internalGameWidget = _GameRenderObjectWidget(widget.game); - - final hasBasicDetectors = hasBasicGestureDetectors(widget.game); - final hasAdvancedDetectors = hasAdvancedGesturesDetectors(widget.game); + final game = widget.game; + Widget internalGameWidget = _GameRenderObjectWidget(game); assert( - !(hasBasicDetectors && hasAdvancedDetectors), - ''' - WARNING: Both Advanced and Basic detectors detected. - Advanced detectors will override basic detectors and the later will not receive events - ''', + !(game is MultiTouchDragDetector && game is PanDetector), + 'WARNING: Both MultiTouchDragDetector and a PanDetector detected. ' + 'The MultiTouchDragDetector will override the PanDetector and it will ' + 'not receive events', ); - if (hasBasicDetectors) { + if (hasBasicGestureDetectors(game)) { internalGameWidget = applyBasicGesturesDetectors( - widget.game, + game, internalGameWidget, ); - } else if (hasAdvancedDetectors) { + } + + if (hasAdvancedGestureDetectors(game)) { internalGameWidget = applyAdvancedGesturesDetectors( - widget.game, + game, internalGameWidget, ); } - if (hasMouseDetectors(widget.game)) { + if (hasMouseDetectors(game)) { internalGameWidget = applyMouseDetectors( - widget.game, + game, internalGameWidget, ); } @@ -312,10 +311,10 @@ class _GameWidgetState extends State> { child: Directionality( textDirection: textDir, child: Container( - color: widget.game.backgroundColor(), + color: game.backgroundColor(), child: LayoutBuilder( builder: (_, BoxConstraints constraints) { - widget.game.onGameResize(constraints.biggest.toVector2()); + game.onGameResize(constraints.biggest.toVector2()); return FutureBuilder( future: loaderFuture, builder: (_, snapshot) { diff --git a/packages/flame/lib/src/game/game_widget/gestures.dart b/packages/flame/lib/src/game/game_widget/gestures.dart index 9b3e395ddd1..00cceca8028 100644 --- a/packages/flame/lib/src/game/game_widget/gestures.dart +++ b/packages/flame/lib/src/game/game_widget/gestures.dart @@ -7,27 +7,30 @@ import '../../gestures/detectors.dart'; import '../../gestures/events.dart'; import '../mixins/game.dart'; -bool hasBasicGestureDetectors(Game game) => - game is TapDetector || - game is SecondaryTapDetector || - game is DoubleTapDetector || - game is LongPressDetector || - game is VerticalDragDetector || - game is HorizontalDragDetector || - game is ForcePressDetector || - game is PanDetector || - game is ScaleDetector; +bool hasBasicGestureDetectors(Game game) { + return game is TapDetector || + game is SecondaryTapDetector || + game is DoubleTapDetector || + game is LongPressDetector || + game is VerticalDragDetector || + game is HorizontalDragDetector || + game is ForcePressDetector || + game is PanDetector || + game is ScaleDetector; +} -bool hasAdvancedGesturesDetectors(Game game) => - game is MultiTouchTapDetector || - game is MultiTouchDragDetector || - game is HasTappables || - game is HasDraggables; +bool hasAdvancedGestureDetectors(Game game) { + return game is MultiTouchTapDetector || + game is MultiTouchDragDetector || + game is HasTappables || + game is HasDraggables; +} -bool hasMouseDetectors(Game game) => - game is MouseMovementDetector || - game is ScrollDetector || - game is HasHoverables; +bool hasMouseDetectors(Game game) { + return game is MouseMovementDetector || + game is ScrollDetector || + game is HasHoverables; +} Widget applyBasicGesturesDetectors(Game game, Widget child) { return GestureDetector( diff --git a/packages/flame/test/game/detectors_test.dart b/packages/flame/test/game/detectors_test.dart new file mode 100644 index 00000000000..f9781ff7488 --- /dev/null +++ b/packages/flame/test/game/detectors_test.dart @@ -0,0 +1,37 @@ +import 'package:flame/game.dart'; +import 'package:flame/input.dart'; +import 'package:flutter_test/flutter_test.dart'; + +class _MultiDragPanGame extends FlameGame + with MultiTouchDragDetector, PanDetector {} + +class _MultiTapDoubleTapGame extends FlameGame + with MultiTouchTapDetector, DoubleTapDetector {} + +void main() { + group('apply detectors', () { + testWidgets( + 'game can not have both MultiTouchDragDetector and PanDetector', + (tester) async { + await tester.pumpWidget( + GameWidget( + game: _MultiDragPanGame(), + ), + ); + expect(tester.takeException(), isInstanceOf()); + }, + ); + + testWidgets( + 'game can have both MultiTouchTapDetector and DoubleTapDetector', + (tester) async { + await tester.pumpWidget( + GameWidget( + game: _MultiTapDoubleTapGame(), + ), + ); + expect(tester.takeException(), null); + }, + ); + }); +}