Refactoring new API to use mixins

This commit is contained in:
Erick Zanardo
2019-11-07 18:34:13 -03:00
committed by Erick (CptBlackPixel)
parent 50fcc2c696
commit a2336b926d
3 changed files with 187 additions and 102 deletions

View File

@ -1,12 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flame/game.dart'; import 'package:flame/game.dart';
import 'package:flame/gestures.dart';
void main() { void main() {
final game = MyGame(); final game = MyGame();
runApp(game.widget); runApp(game.widget);
} }
class MyGame extends Game { class MyGame extends Game with TapDetector, DoubleTapDetector, PanDetector {
final _whitePaint = Paint()..color = const Color(0xFFFFFFFF); final _whitePaint = Paint()..color = const Color(0xFFFFFFFF);
final _bluePaint = Paint()..color = const Color(0xFF0000FF); final _bluePaint = Paint()..color = const Color(0xFF0000FF);
final _greenPaint = Paint()..color = const Color(0xFF00FF00); final _greenPaint = Paint()..color = const Color(0xFF00FF00);
@ -23,18 +24,10 @@ class MyGame extends Game {
void onTap() { void onTap() {
_paint = _paint == _whitePaint ? _bluePaint : _whitePaint; _paint = _paint == _whitePaint ? _bluePaint : _whitePaint;
} }
@override
bool useDoubleTapDetectors() => true;
@override @override
void onDoubleTap() { void onDoubleTap() {
_paint = _greenPaint; _paint = _greenPaint;
} }
@override
bool usePanDetectors() => true;
@override @override
void onPanUpdate(DragUpdateDetails details) { void onPanUpdate(DragUpdateDetails details) {
_rect = _rect.translate(details.delta.dx, details.delta.dy); _rect = _rect.translate(details.delta.dx, details.delta.dy);

View File

@ -13,65 +13,13 @@ import 'components/component.dart';
import 'components/mixins/has_game_ref.dart'; import 'components/mixins/has_game_ref.dart';
import 'components/mixins/tapable.dart'; import 'components/mixins/tapable.dart';
import 'position.dart'; import 'position.dart';
import 'gestures.dart';
/// Represents a generic game. /// Represents a generic game.
/// ///
/// Subclass this to implement the [update] and [render] methods. /// Subclass this to implement the [update] and [render] methods.
/// Flame will deal with calling these methods properly when the game's widget is rendered. /// Flame will deal with calling these methods properly when the game's widget is rendered.
abstract class Game { abstract class Game {
bool useTapDetectors() => true;
void onTap() {}
void onTapCancel() {}
void onTapDown(TapDownDetails details) {}
void onTapUp(TapUpDetails details) {}
bool useSecondaryTapDetectors() => false;
void onSecondaryTapDown(TapDownDetails details) {}
void onSecondaryTapUp(TapUpDetails details) {}
void onSecondaryTapCancel() {}
bool useDoubleTapDetectors() => false;
void onDoubleTap() {}
bool useLongPressDetectors() => false;
void onLongPress() {}
void onLongPressStart(LongPressStartDetails details) {}
void onLongPressMoveUpdate(LongPressMoveUpdateDetails details) {}
void onLongPressUp() {}
void onLongPressEnd(LongPressEndDetails details) {}
bool useVerticalDragDetectors() => false;
void onVerticalDragDown(DragDownDetails details) {}
void onVerticalDragStart(DragStartDetails details) {}
void onVerticalDragUpdate(DragUpdateDetails details) {}
void onVerticalDragEnd(DragEndDetails details) {}
void onVerticalDragCancel() {}
bool useHorizontalDragDetectors() => false;
void onHorizontalDragDown(DragDownDetails details) {}
void onHorizontalDragStart(DragStartDetails details) {}
void onHorizontalDragUpdate(DragUpdateDetails details) {}
void onHorizontalDragEnd(DragEndDetails details) {}
void onHorizontalDragCancel() {}
bool useForcePressDetectors() => false;
void onForcePressStart(ForcePressDetails details) {}
void onForcePressPeak(ForcePressDetails details) {}
void onForcePressUpdate(ForcePressDetails details) {}
void onForcePressEnd(ForcePressDetails details) {}
bool usePanDetectors() => false;
void onPanDown(DragDownDetails details) {}
void onPanStart(DragStartDetails details) {}
void onPanUpdate(DragUpdateDetails details) {}
void onPanEnd(DragEndDetails details) {}
void onPanCancel() {}
bool useScaleDetectors() => false;
void onScaleStart(ScaleStartDetails details) {}
void onScaleUpdate(ScaleUpdateDetails details) {}
void onScaleEnd(ScaleEndDetails details) {}
// Widget Builder for this Game // Widget Builder for this Game
final builder = WidgetBuilder(); final builder = WidgetBuilder();
@ -114,61 +62,142 @@ class WidgetBuilder {
Widget build(Game game) { Widget build(Game game) {
return GestureDetector( return GestureDetector(
// Taps // Taps
onTap: !game.useTapDetectors() ? null : () => game.onTap(), onTap: game is TapDetector ? () => (game as TapDetector).onTap() : null,
onTapCancel: !game.useTapDetectors() ? null : () => game.onTapCancel(), onTapCancel: game is TapDetector
onTapDown: !game.useTapDetectors() ? null : (TapDownDetails d) => game.onTapDown(d), ? () => (game as TapDetector).onTapCancel()
onTapUp: !game.useTapDetectors() ? null : (TapUpDetails d) => game.onTapUp(d), : 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 // Secondary taps
onSecondaryTapDown: !game.useSecondaryTapDetectors() ? null : (TapDownDetails d) => game.onSecondaryTapDown(d), onSecondaryTapDown: game is SecondaryTapDetector
onSecondaryTapUp: !game.useSecondaryTapDetectors() ? null : (TapUpDetails d) => game.onSecondaryTapUp(d), ? (TapDownDetails d) =>
onSecondaryTapCancel: !game.useSecondaryTapDetectors() ? null : () => game.onSecondaryTapCancel(), (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 // Double tap
onDoubleTap: !game.useDoubleTapDetectors() ? null : () => game.onDoubleTap(), onDoubleTap: game is DoubleTapDetector
? () => (game as DoubleTapDetector).onDoubleTap()
: null,
// Long presses // Long presses
onLongPress: !game.useLongPressDetectors() ? null : () => game.onLongPress(), onLongPress: game is LongPressDetector
onLongPressStart: !game.useLongPressDetectors() ? null : (LongPressStartDetails d) => game.onLongPressStart(d), ? () => (game as LongPressDetector).onLongPress()
onLongPressMoveUpdate: !game.useLongPressDetectors() ? null : (LongPressMoveUpdateDetails d) => : null,
game.onLongPressMoveUpdate(d), onLongPressStart: game is LongPressDetector
onLongPressUp: !game.useLongPressDetectors() ? null : () => game.onLongPressUp(), ? (LongPressStartDetails d) =>
onLongPressEnd: !game.useLongPressDetectors() ? null : (LongPressEndDetails d) => game.onLongPressEnd(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 // Vertical drag
onVerticalDragDown: !game.useVerticalDragDetectors() ? null : (DragDownDetails d) => game.onVerticalDragDown(d), onVerticalDragDown: game is VerticalDragDetector
onVerticalDragStart: !game.useVerticalDragDetectors() ? null : (DragStartDetails d) => game.onVerticalDragStart(d), ? (DragDownDetails d) =>
onVerticalDragUpdate: !game.useVerticalDragDetectors() ? null : (DragUpdateDetails d) => (game as VerticalDragDetector).onVerticalDragDown(d)
game.onVerticalDragUpdate(d), : null,
onVerticalDragEnd: !game.useVerticalDragDetectors() ? null : (DragEndDetails d) => game.onVerticalDragEnd(d), onVerticalDragStart: game is VerticalDragDetector
onVerticalDragCancel: !game.useVerticalDragDetectors() ? null : () => game.onVerticalDragCancel(), ? (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 // Horizontal drag
onHorizontalDragDown: !game.useHorizontalDragDetectors() ? null : (DragDownDetails d) => game.onHorizontalDragDown(d), onHorizontalDragDown: game is HorizontalDragDetector
onHorizontalDragStart: !game.useHorizontalDragDetectors() ? null : (DragStartDetails d) => ? (DragDownDetails d) =>
game.onHorizontalDragStart(d), (game as HorizontalDragDetector).onHorizontalDragDown(d)
onHorizontalDragUpdate: !game.useHorizontalDragDetectors() ? null : (DragUpdateDetails d) => : null,
game.onHorizontalDragUpdate(d), onHorizontalDragStart: game is HorizontalDragDetector
onHorizontalDragEnd: !game.useHorizontalDragDetectors() ? null : (DragEndDetails d) => game.onHorizontalDragEnd(d), ? (DragStartDetails d) =>
onHorizontalDragCancel: !game.useHorizontalDragDetectors() ? null : () => game.onHorizontalDragCancel(), (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 // Force presses
onForcePressStart: !game.useForcePressDetectors() ? null : (ForcePressDetails d) => game.onForcePressStart(d), onForcePressStart: game is ForcePressDetector
onForcePressPeak: !game.useForcePressDetectors() ? null : (ForcePressDetails d) => game.onForcePressPeak(d), ? (ForcePressDetails d) =>
onForcePressUpdate: !game.useForcePressDetectors() ? null : (ForcePressDetails d) => game.onForcePressUpdate(d), (game as ForcePressDetector).onForcePressStart(d)
onForcePressEnd: !game.useForcePressDetectors() ? null : (ForcePressDetails d) => game.onForcePressEnd(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 // Pan
onPanDown: !game.usePanDetectors() ? null : (DragDownDetails d) => game.onPanDown(d), onPanDown: game is PanDetector
onPanStart: !game.usePanDetectors() ? null : (DragStartDetails d) => game.onPanStart(d), ? (DragDownDetails d) => (game as PanDetector).onPanDown(d)
onPanUpdate: !game.usePanDetectors() ? null : (DragUpdateDetails d) => game.onPanUpdate(d), : null,
onPanEnd: !game.usePanDetectors() ? null : (DragEndDetails d) => game.onPanEnd(d), onPanStart: game is PanDetector
onPanCancel: !game.usePanDetectors() ? null : () => game.onPanCancel(), ? (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 // Scales
onScaleStart: !game.useScaleDetectors() ? null : (ScaleStartDetails d) => game.onScaleStart(d), onScaleStart: game is ScaleDetector
onScaleUpdate: !game.useScaleDetectors() ? null : (ScaleUpdateDetails d) => game.onScaleUpdate(d), ? (ScaleStartDetails d) => (game as ScaleDetector).onScaleStart(d)
onScaleEnd: !game.useScaleDetectors() ? null : (ScaleEndDetails d) => game.onScaleEnd(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( child: Container(
color: const Color(0xFF000000), color: const Color(0xFF000000),
@ -184,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. /// 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. /// This is the recommended structure to use for most games.
/// It is based on the Component system. /// 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. /// The list of components to be updated and rendered by the base game.
OrderedSet<Component> components = OrderedSet<Component> components =
OrderedSet(Comparing.on((c) => c.priority())); OrderedSet(Comparing.on((c) => c.priority()));

63
lib/gestures.dart Normal file
View 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) {}
}