From 09b00a14a1aa7fe60f9096d699334daf603f083a Mon Sep 17 00:00:00 2001 From: Allison Ryan Date: Mon, 2 May 2022 15:18:29 -0500 Subject: [PATCH] feat: connect dino bonus --- lib/game/components/components.dart | 2 +- .../dino_desert/behaviors/behaviors.dart | 1 + .../behaviors/chrome_dino_bonus_behavior.dart | 24 +++++++ .../{ => dino_desert}/dino_desert.dart | 13 +++- .../chrome_dino_chomping_behavior.dart | 6 +- .../chrome_dino_chomping_behavior_test.dart | 3 +- .../chrome_dino_bonus_behavior_test.dart | 63 +++++++++++++++++++ .../{ => dino_desert}/dino_desert_test.dart | 30 ++++++--- 8 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 lib/game/components/dino_desert/behaviors/behaviors.dart create mode 100644 lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart rename lib/game/components/{ => dino_desert}/dino_desert.dart (73%) create mode 100644 test/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior_test.dart rename test/game/components/{ => dino_desert}/dino_desert_test.dart (70%) diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index aeb5742e..2801a4b3 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -4,7 +4,7 @@ export 'camera_controller.dart'; export 'controlled_ball.dart'; export 'controlled_flipper.dart'; export 'controlled_plunger.dart'; -export 'dino_desert.dart'; +export 'dino_desert/dino_desert.dart'; export 'drain.dart'; export 'flutter_forest/flutter_forest.dart'; export 'game_flow_controller.dart'; diff --git a/lib/game/components/dino_desert/behaviors/behaviors.dart b/lib/game/components/dino_desert/behaviors/behaviors.dart new file mode 100644 index 00000000..fe802c88 --- /dev/null +++ b/lib/game/components/dino_desert/behaviors/behaviors.dart @@ -0,0 +1 @@ +export 'chrome_dino_bonus_behavior.dart'; diff --git a/lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart b/lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart new file mode 100644 index 00000000..e4d69f9c --- /dev/null +++ b/lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart @@ -0,0 +1,24 @@ +import 'package:flame/components.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +/// Adds a [GameBonus.dinoChomp] when a [Ball] is chomped by the [ChromeDino]. +class ChromeDinoBonusBehavior extends Component + with HasGameRef, ParentIsA { + @override + void onMount() { + super.onMount(); + final chromeDino = parent.firstChild()!; + + // TODO(alestiago): Refactor subscription management once the following is + // merged: + // https://github.com/flame-engine/flame/pull/1538 + chromeDino.bloc.stream.listen((state) { + final listenWhen = state.status == ChromeDinoStatus.chomping; + if (!listenWhen) return; + + gameRef.read().add(const BonusActivated(GameBonus.dinoChomp)); + }); + } +} diff --git a/lib/game/components/dino_desert.dart b/lib/game/components/dino_desert/dino_desert.dart similarity index 73% rename from lib/game/components/dino_desert.dart rename to lib/game/components/dino_desert/dino_desert.dart index b3ae4ab9..4d8cd7b6 100644 --- a/lib/game/components/dino_desert.dart +++ b/lib/game/components/dino_desert/dino_desert.dart @@ -1,11 +1,13 @@ import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball/game/components/dino_desert/behaviors/behaviors.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; /// {@template dino_desert} -/// Area located next to the [Launcher] containing the [ChromeDino] and -/// [DinoWalls]. +/// Area located next to the [Launcher] containing the [ChromeDino], +/// [DinoWalls], and the [Slingshots]. /// {@endtemplate} class DinoDesert extends Component { /// {@macro dino_desert} @@ -21,8 +23,15 @@ class DinoDesert extends Component { _BarrierBehindDino(), DinoWalls(), Slingshots(), + ChromeDinoBonusBehavior(), ], ); + + /// Creates [DinoDesert] without any children. + /// + /// This can be used for testing [DinoDesert]'s behaviors in isolation. + @visibleForTesting + DinoDesert.test(); } class _BarrierBehindDino extends BodyComponent { diff --git a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior.dart b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior.dart index eff84ff4..c8a19d18 100644 --- a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior.dart +++ b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior.dart @@ -14,7 +14,9 @@ class ChromeDinoChompingBehavior extends ContactBehavior { super.beginContact(other, contact); if (other is! Ball) return; - other.firstChild()!.setOpacity(0); - parent.bloc.onChomp(other); + if (parent.bloc.state.status != ChromeDinoStatus.chomping) { + other.firstChild()!.setOpacity(0); + parent.bloc.onChomp(other); + } } } diff --git a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart index 141d89de..ae3b9500 100644 --- a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart +++ b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart @@ -26,7 +26,8 @@ void main() { }); flameTester.test( - 'beginContact sets ball sprite to be invisible and calls onChomp', + 'beginContact sets ball sprite to be invisible and calls onChomp ' + 'when status is not chomping', (game) async { final ball = Ball(baseColor: Colors.red); final behavior = ChromeDinoChompingBehavior(); diff --git a/test/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior_test.dart b/test/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior_test.dart new file mode 100644 index 00000000..3b8f2dfa --- /dev/null +++ b/test/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior_test.dart @@ -0,0 +1,63 @@ +// ignore_for_file: cascade_invocations + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/components/dino_desert/behaviors/behaviors.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart'; + +import '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final assets = [ + Assets.images.dino.animatronic.head.keyName, + Assets.images.dino.animatronic.mouth.keyName, + Assets.images.dino.topWall.keyName, + Assets.images.dino.bottomWall.keyName, + Assets.images.slingshot.upper.keyName, + Assets.images.slingshot.lower.keyName, + ]; + + group('ChromeDinoBonusBehavior', () { + late GameBloc gameBloc; + + setUp(() { + gameBloc = MockGameBloc(); + whenListen( + gameBloc, + const Stream.empty(), + initialState: const GameState.initial(), + ); + }); + + final flameBlocTester = FlameBlocTester( + gameBuilder: EmptyPinballTestGame.new, + blocBuilder: () => gameBloc, + assets: assets, + ); + + flameBlocTester.testGameWidget( + 'adds GameBonus.dinoChomp to the game ' + 'when ChromeDinoStatus.chomping is emitted', + setUp: (game, tester) async { + final behavior = ChromeDinoBonusBehavior(); + final parent = DinoDesert.test(); + final chromeDino = ChromeDino(); + + await parent.add(chromeDino); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + + chromeDino.bloc.onChomp(MockBall()); + await tester.pump(); + + verify( + () => gameBloc.add(const BonusActivated(GameBonus.dinoChomp)), + ).called(1); + }, + ); + }); +} diff --git a/test/game/components/dino_desert_test.dart b/test/game/components/dino_desert/dino_desert_test.dart similarity index 70% rename from test/game/components/dino_desert_test.dart rename to test/game/components/dino_desert/dino_desert_test.dart index 35a2d25b..262ddc2d 100644 --- a/test/game/components/dino_desert_test.dart +++ b/test/game/components/dino_desert/dino_desert_test.dart @@ -2,10 +2,11 @@ import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/game/components/dino_desert/behaviors/behaviors.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -import '../../helpers/helpers.dart'; +import '../../../helpers/helpers.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -63,17 +64,28 @@ void main() { ); }); - flameTester.test( - 'adds ScoringBehavior to ChromeDino', - (game) async { - await game.ensureAdd(DinoDesert()); + group('adds', () { + flameTester.test( + 'ScoringBehavior to ChromeDino', + (game) async { + await game.ensureAdd(DinoDesert()); - final chromeDino = game.descendants().whereType().single; + final chromeDino = game.descendants().whereType().single; + expect( + chromeDino.firstChild(), + isNotNull, + ); + }, + ); + + flameTester.test('a ChromeDinoBonusBehavior', (game) async { + final dinoDesert = DinoDesert(); + await game.ensureAdd(dinoDesert); expect( - chromeDino.firstChild(), + dinoDesert.children.whereType().single, isNotNull, ); - }, - ); + }); + }); }); }