From c5b271003ca01d236eacf650416743a508331599 Mon Sep 17 00:00:00 2001 From: alestiago Date: Wed, 30 Mar 2022 16:41:43 +0100 Subject: [PATCH] feat: implemented ComponentController --- lib/game/components/ball.dart | 72 ++----------------- lib/game/components/board.dart | 2 +- lib/game/components/flipper_controller.dart | 17 ++--- lib/game/components/flutter_forest.dart | 9 ++- lib/game/components/score_points.dart | 13 +++- lib/game/components/wall.dart | 9 ++- lib/game/pinball_game.dart | 24 +++---- .../lib/src/components/ball.dart | 2 +- 8 files changed, 50 insertions(+), 98 deletions(-) diff --git a/lib/game/components/ball.dart b/lib/game/components/ball.dart index 9f6241fd..91eb2571 100644 --- a/lib/game/components/ball.dart +++ b/lib/game/components/ball.dart @@ -1,62 +1,15 @@ import 'package:flame/components.dart'; +import 'package:pinball/flame/flame.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -/// {@template ball_type} -/// Specifies the type of [Ball]. -/// -/// Different [BallType]s are affected by different game mechanics. -/// {@endtemplate} -enum BallType { - /// A [Ball] spawned from the [Plunger]. - /// - /// [normal] balls decrease the [GameState.balls] when they fall through the - /// the [BottomWall]. - normal, - - /// A [Ball] that does not alter [GameState.balls]. - /// - /// For example, a [Ball] spawned by Dash in the [FlutterForest]. - extra, -} - -/// {@template ball_blueprint} -/// [Blueprint] which cretes a ball game object. -/// {@endtemplate} -class BallBlueprint extends Blueprint { - /// {@macro ball_blueprint} - BallBlueprint({ - required this.position, - required this.type, - }); - - /// The initial position of the [Ball]. - final Vector2 position; - - /// {@macro ball_type} - final BallType type; - - @override - void build(PinballGame gameRef) { - final baseColor = gameRef.theme.characterTheme.ballColor; - final ball = Ball(baseColor: baseColor) - ..add( - BallController(type: type), - ); - - add(ball..initialPosition = position + Vector2(0, ball.size.y / 2)); - } -} - /// {@template ball_controller} /// Controller attached to a [Ball] that handles its game related logic. /// {@endtemplate} -class BallController extends Component with HasGameRef { +class BallController extends ComponentController + with HasGameRef { /// {@macro ball_controller} - BallController({required this.type}); - - /// {@macro ball_type} - final BallType type; + BallController(Ball ball) : super(ball); /// Removes the [Ball] from a [PinballGame]; spawning a new [Ball] if /// any are left. @@ -64,24 +17,9 @@ class BallController extends Component with HasGameRef { /// Triggered by [BottomWallBallContactCallback] when the [Ball] falls into /// a [BottomWall]. void lost() { - parent?.shouldRemove = true; - // TODO(alestiago): Consider adding test for this logic once we remove the - // BallX extension. - if (type != BallType.normal) return; - final bloc = gameRef.read()..add(const BallLost()); final shouldBallRespwan = !bloc.state.isLastBall && !bloc.state.isGameOver; - if (shouldBallRespwan) { - gameRef.spawnBall(); - } - } -} -/// Adds helper methods to the [Ball] -extension BallX on Ball { - /// Returns the controller instance of the ball - // TODO(erickzanardo): Remove the need of an extension. - BallController get controller { - return children.whereType().first; + if (shouldBallRespwan) gameRef.spawnBall(); } } diff --git a/lib/game/components/board.dart b/lib/game/components/board.dart index fb6dcda3..c634960b 100644 --- a/lib/game/components/board.dart +++ b/lib/game/components/board.dart @@ -97,7 +97,7 @@ class _BottomGroupSide extends Component { final flipper = Flipper( side: _side, )..initialPosition = _position; - await flipper.add(FlipperController(flipper)); + await FlipperController(flipper).attach(); final baseboard = Baseboard(side: _side) ..initialPosition = _position + diff --git a/lib/game/components/flipper_controller.dart b/lib/game/components/flipper_controller.dart index 946cfd49..1330c70d 100644 --- a/lib/game/components/flipper_controller.dart +++ b/lib/game/components/flipper_controller.dart @@ -1,16 +1,17 @@ import 'package:flame/components.dart'; import 'package:flutter/services.dart'; +import 'package:pinball/flame/flame.dart'; import 'package:pinball_components/pinball_components.dart'; /// {@template flipper_controller} -/// A [Component] that controls the [Flipper]s movement. +/// A [ComponentController] that controls a [Flipper]s movement. /// {@endtemplate} -class FlipperController extends Component with KeyboardHandler { +class FlipperController extends ComponentController + with KeyboardHandler { /// {@macro flipper_controller} - FlipperController(this.flipper) : _keys = flipper.side.flipperKeys; - - /// The [Flipper] this controller is controlling. - final Flipper flipper; + FlipperController(Flipper flipper) + : _keys = flipper.side.flipperKeys, + super(flipper); /// The [LogicalKeyboardKey]s that will control the [Flipper]. /// @@ -25,9 +26,9 @@ class FlipperController extends Component with KeyboardHandler { if (!_keys.contains(event.logicalKey)) return true; if (event is RawKeyDownEvent) { - flipper.moveUp(); + component.moveUp(); } else if (event is RawKeyUpEvent) { - flipper.moveDown(); + component.moveDown(); } return false; diff --git a/lib/game/components/flutter_forest.dart b/lib/game/components/flutter_forest.dart index c5ed20bf..a5544ac8 100644 --- a/lib/game/components/flutter_forest.dart +++ b/lib/game/components/flutter_forest.dart @@ -31,11 +31,10 @@ class FlutterForest extends Component @override void onNewState(GameState state) { super.onNewState(state); - gameRef.addFromBlueprint( - BallBlueprint( - position: Vector2(17.2, 52.7), - type: BallType.extra, - ), + gameRef.add( + Ball( + baseColor: gameRef.theme.characterTheme.ballColor, + )..initialPosition = Vector2(17.2, 52.7), ); } diff --git a/lib/game/components/score_points.dart b/lib/game/components/score_points.dart index 12649137..39910777 100644 --- a/lib/game/components/score_points.dart +++ b/lib/game/components/score_points.dart @@ -18,16 +18,23 @@ mixin ScorePoints on BodyComponent { } } +/// {@template ball_score_points_callbacks} /// Adds points to the score when a [Ball] collides with a [BodyComponent] that /// implements [ScorePoints]. +/// {@endtemplate} class BallScorePointsCallback extends ContactCallback { + /// {@macro ball_score_points_callbacks} + BallScorePointsCallback(PinballGame game) : _gameRef = game; + + final PinballGame _gameRef; + @override void begin( - Ball ball, + Ball _, ScorePoints scorePoints, - Contact _, + Contact __, ) { - ball.controller.gameRef.read().add( + _gameRef.read().add( Scored(points: scorePoints.points), ); } diff --git a/lib/game/components/wall.dart b/lib/game/components/wall.dart index 0fb57a41..1acce4d3 100644 --- a/lib/game/components/wall.dart +++ b/lib/game/components/wall.dart @@ -78,6 +78,13 @@ class BottomWall extends Wall { class BottomWallBallContactCallback extends ContactCallback { @override void begin(Ball ball, BottomWall wall, Contact contact) { - ball.controller.lost(); + ball.shouldRemove = true; + + // TODO(alestiago): replace with .firstChild when available. + late final BallController? controller; + final children = ball.children.whereType(); + controller = children.isEmpty ? null : children.first; + + if (controller != null) controller.lost(); } } diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index 9673b2d2..6505bd09 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -68,7 +68,7 @@ class PinballGame extends Forge2DGame } void _addContactCallbacks() { - addContactCallback(BallScorePointsCallback()); + addContactCallback(BallScorePointsCallback(this)); addContactCallback(BottomWallBallContactCallback()); addContactCallback(BonusLetterBallContactCallback()); } @@ -101,12 +101,14 @@ class PinballGame extends Forge2DGame } void spawnBall() { - addFromBlueprint( - BallBlueprint( - position: plunger.body.position, - type: BallType.normal, - ), - ); + final ball = Ball( + baseColor: theme.characterTheme.ballColor, + )..initialPosition = Vector2( + plunger.body.position.x, + plunger.body.position.y + Ball.size.y, + ); + BallController(ball).attach(); + add(ball); } } @@ -138,11 +140,9 @@ class DebugPinballGame extends PinballGame with TapDetector { @override void onTapUp(TapUpInfo info) { - addFromBlueprint( - BallBlueprint( - position: info.eventPosition.game, - type: BallType.extra, - ), + add( + Ball(baseColor: const Color(0xFFFF0000)) + ..initialPosition = info.eventPosition.game, ); } } diff --git a/packages/pinball_components/lib/src/components/ball.dart b/packages/pinball_components/lib/src/components/ball.dart index 9a2da898..96e0bf9d 100644 --- a/packages/pinball_components/lib/src/components/ball.dart +++ b/packages/pinball_components/lib/src/components/ball.dart @@ -23,7 +23,7 @@ class Ball extends BodyComponent } /// The size of the [Ball] - final Vector2 size = Vector2.all(3); + static final Vector2 size = Vector2.all(3); /// The base [Color] used to tint this [Ball] final Color baseColor;