From cc3ba899ce644c35844685580d250e4b924f08a0 Mon Sep 17 00:00:00 2001 From: Rui Miguel Alonso Date: Sat, 30 Apr 2022 16:38:43 +0200 Subject: [PATCH] feat: implemented `Multipliers` (#231) * feat: added multipliers * feat: added multipliers to sandbox * test: tests and golden tests for multipliers * feat: multipliers controller * fix: missed assets load * refactor: multiplier refactored and tested * refactor: changed sandbox for multipliers * feat: multiplier controller * refactor: moved assets to constructor at sandbox * test: coverage for multipliers * test: removed test * refactor: coverage for multiplier * test: coverage for multiplier * chore: multiplier doc * Update packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart Co-authored-by: Alejandro Santiago * chore: little code refactor, doc * refactor: multiplier creation refactored * test: fixed tests for multipliers * refactor: changed properties names * refactor: multipliers cubit * test: refactored tests for multipliers * refactored: sandbow for multipliers * refactor: multipliers controller * test: tests for multiplier behavior * chore: analysis errors * feat: multipliers behavior with multiplier from gamebloc * refactor: changed toggle to next at multipliers * test: coverage for cubit * refactor: refactored multipliers and coverage * refactor: sandbox * test: flamebloctester * Update lib/game/components/multipliers/multipliers.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * Update packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_cubit.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * Update lib/game/components/multipliers/multipliers.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * Update packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_state.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * Update packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_state.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * Update test/game/components/multipliers/behaviors/multipliers_behavior_test.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * test: fixed test names and golden files * test: golden tests * fix: fixed bloc bug for tests on multiplier behavior * chore: renamed rotation * chore: doc ignore * test: grouped * test: golden tests dir * Update packages/pinball_components/sandbox/lib/stories/multipliers/stories.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * refactor: moved extension for multiplier value * chore: multiplier extension equalsTo name * fixed: missed method rename Co-authored-by: Alejandro Santiago Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> --- lib/game/components/components.dart | 1 + .../multipliers/behaviors/behaviors.dart | 1 + .../behaviors/multipliers_behavior.dart | 25 + .../components/multipliers/multipliers.dart | 44 ++ lib/game/game_assets.dart | 10 + lib/game/pinball_game.dart | 1 + .../assets/images/multiplier/x2/dimmed.png | Bin 0 -> 5251 bytes .../assets/images/multiplier/x2/lit.png | Bin 0 -> 5701 bytes .../assets/images/multiplier/x3/dimmed.png | Bin 0 -> 6358 bytes .../assets/images/multiplier/x3/lit.png | Bin 0 -> 7036 bytes .../assets/images/multiplier/x4/dimmed.png | Bin 0 -> 9234 bytes .../assets/images/multiplier/x4/lit.png | Bin 0 -> 10603 bytes .../assets/images/multiplier/x5/dimmed.png | Bin 0 -> 11535 bytes .../assets/images/multiplier/x5/lit.png | Bin 0 -> 13077 bytes .../assets/images/multiplier/x6/dimmed.png | Bin 0 -> 11417 bytes .../assets/images/multiplier/x6/lit.png | Bin 0 -> 13227 bytes .../lib/gen/assets.gen.dart | 72 +++ .../lib/src/components/components.dart | 1 + .../multiplier/cubit/multiplier_cubit.dart | 25 + .../multiplier/cubit/multiplier_state.dart | 56 ++ .../src/components/multiplier/multiplier.dart | 204 +++++++ packages/pinball_components/pubspec.yaml | 5 + .../pinball_components/sandbox/lib/main.dart | 1 + .../stories/multipliers/multipliers_game.dart | 97 ++++ .../lib/stories/multipliers/stories.dart | 11 + .../sandbox/lib/stories/stories.dart | 1 + .../pinball_components/sandbox/pubspec.lock | 19 +- .../test/helpers/mocks.dart | 2 + .../golden/multipliers/x2-dimmed.png | Bin 0 -> 23391 bytes .../components/golden/multipliers/x2-lit.png | Bin 0 -> 23847 bytes .../golden/multipliers/x3-dimmed.png | Bin 0 -> 23695 bytes .../components/golden/multipliers/x3-lit.png | Bin 0 -> 24555 bytes .../golden/multipliers/x4-dimmed.png | Bin 0 -> 24352 bytes .../components/golden/multipliers/x4-lit.png | Bin 0 -> 25722 bytes .../golden/multipliers/x5-dimmed.png | Bin 0 -> 24980 bytes .../components/golden/multipliers/x5-lit.png | Bin 0 -> 26830 bytes .../golden/multipliers/x6-dimmed.png | Bin 0 -> 25145 bytes .../components/golden/multipliers/x6-lit.png | Bin 0 -> 26854 bytes .../cubit/multiplier_cubit_test.dart | 118 ++++ .../cubit/multiplier_state_test.dart | 75 +++ .../multiplier/multiplier_test.dart | 517 ++++++++++++++++++ .../behaviors/multipliers_behavior_test.dart | 133 +++++ .../multipliers/multipliers_test.dart | 63 +++ test/game/pinball_game_test.dart | 38 +- test/helpers/mocks.dart | 8 + 45 files changed, 1516 insertions(+), 12 deletions(-) create mode 100644 lib/game/components/multipliers/behaviors/behaviors.dart create mode 100644 lib/game/components/multipliers/behaviors/multipliers_behavior.dart create mode 100644 lib/game/components/multipliers/multipliers.dart create mode 100644 packages/pinball_components/assets/images/multiplier/x2/dimmed.png create mode 100644 packages/pinball_components/assets/images/multiplier/x2/lit.png create mode 100644 packages/pinball_components/assets/images/multiplier/x3/dimmed.png create mode 100644 packages/pinball_components/assets/images/multiplier/x3/lit.png create mode 100644 packages/pinball_components/assets/images/multiplier/x4/dimmed.png create mode 100644 packages/pinball_components/assets/images/multiplier/x4/lit.png create mode 100644 packages/pinball_components/assets/images/multiplier/x5/dimmed.png create mode 100644 packages/pinball_components/assets/images/multiplier/x5/lit.png create mode 100644 packages/pinball_components/assets/images/multiplier/x6/dimmed.png create mode 100644 packages/pinball_components/assets/images/multiplier/x6/lit.png create mode 100644 packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_cubit.dart create mode 100644 packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_state.dart create mode 100644 packages/pinball_components/lib/src/components/multiplier/multiplier.dart create mode 100644 packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart create mode 100644 packages/pinball_components/sandbox/lib/stories/multipliers/stories.dart create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x2-dimmed.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x2-lit.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x3-dimmed.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x3-lit.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x4-dimmed.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x4-lit.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x5-dimmed.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x5-lit.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x6-dimmed.png create mode 100644 packages/pinball_components/test/src/components/golden/multipliers/x6-lit.png create mode 100644 packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart create mode 100644 packages/pinball_components/test/src/components/multiplier/cubit/multiplier_state_test.dart create mode 100644 packages/pinball_components/test/src/components/multiplier/multiplier_test.dart create mode 100644 test/game/components/multipliers/behaviors/multipliers_behavior_test.dart create mode 100644 test/game/components/multipliers/multipliers_test.dart diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 3fae6abd..afef04f0 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -10,5 +10,6 @@ export 'flutter_forest/flutter_forest.dart'; export 'game_flow_controller.dart'; export 'google_word/google_word.dart'; export 'launcher.dart'; +export 'multipliers/multipliers.dart'; export 'scoring_behavior.dart'; export 'sparky_fire_zone.dart'; diff --git a/lib/game/components/multipliers/behaviors/behaviors.dart b/lib/game/components/multipliers/behaviors/behaviors.dart new file mode 100644 index 00000000..70703bba --- /dev/null +++ b/lib/game/components/multipliers/behaviors/behaviors.dart @@ -0,0 +1 @@ +export 'multipliers_behavior.dart'; diff --git a/lib/game/components/multipliers/behaviors/multipliers_behavior.dart b/lib/game/components/multipliers/behaviors/multipliers_behavior.dart new file mode 100644 index 00000000..33a59a08 --- /dev/null +++ b/lib/game/components/multipliers/behaviors/multipliers_behavior.dart @@ -0,0 +1,25 @@ +import 'package:flame/components.dart'; +import 'package:flame_bloc/flame_bloc.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +/// Toggle each [Multiplier] when GameState.multiplier changes. +class MultipliersBehavior extends Component + with + HasGameRef, + ParentIsA, + BlocComponent { + @override + bool listenWhen(GameState? previousState, GameState newState) { + return previousState?.multiplier != newState.multiplier; + } + + @override + void onNewState(GameState state) { + final multipliers = parent.children.whereType(); + for (final multiplier in multipliers) { + multiplier.bloc.next(state.multiplier); + } + } +} diff --git a/lib/game/components/multipliers/multipliers.dart b/lib/game/components/multipliers/multipliers.dart new file mode 100644 index 00000000..6a6a1563 --- /dev/null +++ b/lib/game/components/multipliers/multipliers.dart @@ -0,0 +1,44 @@ +import 'dart:math' as math; +import 'package:flame/components.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball/game/components/multipliers/behaviors/behaviors.dart'; +import 'package:pinball_components/pinball_components.dart'; + +/// {@template multipliers} +/// A group for the multipliers on the board. +/// {@endtemplate} +class Multipliers extends Component { + /// {@macro multipliers} + Multipliers() + : super( + children: [ + Multiplier.x2( + position: Vector2(-19.5, -2), + angle: -15 * math.pi / 180, + ), + Multiplier.x3( + position: Vector2(13, -9.4), + angle: 15 * math.pi / 180, + ), + Multiplier.x4( + position: Vector2(0, -21.2), + angle: 0, + ), + Multiplier.x5( + position: Vector2(-8.5, -28), + angle: -3 * math.pi / 180, + ), + Multiplier.x6( + position: Vector2(10, -30.7), + angle: 8 * math.pi / 180, + ), + MultipliersBehavior(), + ], + ); + + /// Creates [Multipliers] without any children. + /// + /// This can be used for testing [Multipliers]'s behaviors in isolation. + @visibleForTesting + Multipliers.test(); +} diff --git a/lib/game/game_assets.dart b/lib/game/game_assets.dart index cb62d929..a8c3c82e 100644 --- a/lib/game/game_assets.dart +++ b/lib/game/game_assets.dart @@ -103,6 +103,16 @@ extension PinballGameAssetsX on PinballGame { images.load(components.Assets.images.googleWord.letter5.keyName), images.load(components.Assets.images.googleWord.letter6.keyName), images.load(components.Assets.images.backboard.display.keyName), + images.load(components.Assets.images.multiplier.x2.lit.keyName), + images.load(components.Assets.images.multiplier.x2.dimmed.keyName), + images.load(components.Assets.images.multiplier.x3.lit.keyName), + images.load(components.Assets.images.multiplier.x3.dimmed.keyName), + images.load(components.Assets.images.multiplier.x4.lit.keyName), + images.load(components.Assets.images.multiplier.x4.dimmed.keyName), + images.load(components.Assets.images.multiplier.x5.lit.keyName), + images.load(components.Assets.images.multiplier.x5.dimmed.keyName), + images.load(components.Assets.images.multiplier.x6.lit.keyName), + images.load(components.Assets.images.multiplier.x6.dimmed.keyName), images.load(dashTheme.leaderboardIcon.keyName), images.load(sparkyTheme.leaderboardIcon.keyName), images.load(androidTheme.leaderboardIcon.keyName), diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index a4b740fb..262a3e29 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -53,6 +53,7 @@ class PinballGame extends Forge2DGame final launcher = Launcher(); unawaited(addFromBlueprint(launcher)); + await add(Multipliers()); await add(FlutterForest()); await addFromBlueprint(SparkyFireZone()); await addFromBlueprint(AndroidAcres()); diff --git a/packages/pinball_components/assets/images/multiplier/x2/dimmed.png b/packages/pinball_components/assets/images/multiplier/x2/dimmed.png new file mode 100644 index 0000000000000000000000000000000000000000..7cc9fc4f56cb4b80198c0753fcb73c8caf613215 GIT binary patch literal 5251 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 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/assets/images/multiplier/x3/lit.png b/packages/pinball_components/assets/images/multiplier/x3/lit.png new file mode 100644 index 0000000000000000000000000000000000000000..7fdedbbe857b1c7b9b5775392facdaa92f4f0616 GIT binary patch literal 7036 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 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/assets/images/multiplier/x4/dimmed.png b/packages/pinball_components/assets/images/multiplier/x4/dimmed.png new file mode 100644 index 0000000000000000000000000000000000000000..e8a6256e0430c762282b8e4911111a1a9ff123a0 GIT binary patch literal 9234 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 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/assets/images/multiplier/x5/dimmed.png b/packages/pinball_components/assets/images/multiplier/x5/dimmed.png new file mode 100644 index 0000000000000000000000000000000000000000..96e018e466597f624bed8e3e387bd1251d904d8e GIT binary patch literal 11535 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 BmbCx? literal 0 HcmV?d00001 diff --git a/packages/pinball_components/assets/images/multiplier/x5/lit.png b/packages/pinball_components/assets/images/multiplier/x5/lit.png new file mode 100644 index 0000000000000000000000000000000000000000..23fd3aaba384699c2843a40ed11f29cbb013df87 GIT binary patch literal 13077 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 j_*xWQx$TjwLjfZvDW>V2f0l3Ut!=q@5oC8^ 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

    VCzd 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 const $AssetsImagesKickerGen(); $AssetsImagesLaunchRampGen get launchRamp => const $AssetsImagesLaunchRampGen(); + $AssetsImagesMultiplierGen get multiplier => + const $AssetsImagesMultiplierGen(); $AssetsImagesPlungerGen get plunger => const $AssetsImagesPlungerGen(); $AssetsImagesSignpostGen get signpost => const $AssetsImagesSignpostGen(); $AssetsImagesSlingshotGen get slingshot => const $AssetsImagesSlingshotGen(); @@ -190,6 +192,16 @@ class $AssetsImagesLaunchRampGen { const AssetGenImage('assets/images/launch_ramp/ramp.png'); } +class $AssetsImagesMultiplierGen { + const $AssetsImagesMultiplierGen(); + + $AssetsImagesMultiplierX2Gen get x2 => const $AssetsImagesMultiplierX2Gen(); + $AssetsImagesMultiplierX3Gen get x3 => const $AssetsImagesMultiplierX3Gen(); + $AssetsImagesMultiplierX4Gen get x4 => const $AssetsImagesMultiplierX4Gen(); + $AssetsImagesMultiplierX5Gen get x5 => const $AssetsImagesMultiplierX5Gen(); + $AssetsImagesMultiplierX6Gen get x6 => const $AssetsImagesMultiplierX6Gen(); +} + class $AssetsImagesPlungerGen { const $AssetsImagesPlungerGen(); @@ -321,6 +333,66 @@ class $AssetsImagesDinoAnimatronicGen { const AssetGenImage('assets/images/dino/animatronic/mouth.png'); } +class $AssetsImagesMultiplierX2Gen { + const $AssetsImagesMultiplierX2Gen(); + + /// File path: assets/images/multiplier/x2/dimmed.png + AssetGenImage get dimmed => + const AssetGenImage('assets/images/multiplier/x2/dimmed.png'); + + /// File path: assets/images/multiplier/x2/lit.png + AssetGenImage get lit => + const AssetGenImage('assets/images/multiplier/x2/lit.png'); +} + +class $AssetsImagesMultiplierX3Gen { + const $AssetsImagesMultiplierX3Gen(); + + /// File path: assets/images/multiplier/x3/dimmed.png + AssetGenImage get dimmed => + const AssetGenImage('assets/images/multiplier/x3/dimmed.png'); + + /// File path: assets/images/multiplier/x3/lit.png + AssetGenImage get lit => + const AssetGenImage('assets/images/multiplier/x3/lit.png'); +} + +class $AssetsImagesMultiplierX4Gen { + const $AssetsImagesMultiplierX4Gen(); + + /// File path: assets/images/multiplier/x4/dimmed.png + AssetGenImage get dimmed => + const AssetGenImage('assets/images/multiplier/x4/dimmed.png'); + + /// File path: assets/images/multiplier/x4/lit.png + AssetGenImage get lit => + const AssetGenImage('assets/images/multiplier/x4/lit.png'); +} + +class $AssetsImagesMultiplierX5Gen { + const $AssetsImagesMultiplierX5Gen(); + + /// File path: assets/images/multiplier/x5/dimmed.png + AssetGenImage get dimmed => + const AssetGenImage('assets/images/multiplier/x5/dimmed.png'); + + /// File path: assets/images/multiplier/x5/lit.png + AssetGenImage get lit => + const AssetGenImage('assets/images/multiplier/x5/lit.png'); +} + +class $AssetsImagesMultiplierX6Gen { + const $AssetsImagesMultiplierX6Gen(); + + /// File path: assets/images/multiplier/x6/dimmed.png + AssetGenImage get dimmed => + const AssetGenImage('assets/images/multiplier/x6/dimmed.png'); + + /// File path: assets/images/multiplier/x6/lit.png + AssetGenImage get lit => + const AssetGenImage('assets/images/multiplier/x6/lit.png'); +} + class $AssetsImagesSpaceshipRailGen { const $AssetsImagesSpaceshipRailGen(); diff --git a/packages/pinball_components/lib/src/components/components.dart b/packages/pinball_components/lib/src/components/components.dart index c6c5c802..f16aa0a6 100644 --- a/packages/pinball_components/lib/src/components/components.dart +++ b/packages/pinball_components/lib/src/components/components.dart @@ -19,6 +19,7 @@ export 'kicker.dart'; export 'launch_ramp.dart'; export 'layer.dart'; export 'layer_sensor.dart'; +export 'multiplier/multiplier.dart'; export 'plunger.dart'; export 'render_priority.dart'; export 'rocket.dart'; diff --git a/packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_cubit.dart b/packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_cubit.dart new file mode 100644 index 00000000..1d265b2e --- /dev/null +++ b/packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_cubit.dart @@ -0,0 +1,25 @@ +// ignore_for_file: public_member_api_docs + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:pinball_components/pinball_components.dart'; + +part 'multiplier_state.dart'; + +class MultiplierCubit extends Cubit { + MultiplierCubit(MultiplierValue multiplierValue) + : super(MultiplierState.initial(multiplierValue)); + + /// Event added when the game's current multiplier changes. + void next(int multiplier) { + if (state.value.equals(multiplier)) { + if (state.spriteState == MultiplierSpriteState.dimmed) { + emit(state.copyWith(spriteState: MultiplierSpriteState.lit)); + } + } else { + if (state.spriteState == MultiplierSpriteState.lit) { + emit(state.copyWith(spriteState: MultiplierSpriteState.dimmed)); + } + } + } +} diff --git a/packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_state.dart b/packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_state.dart new file mode 100644 index 00000000..e3adde70 --- /dev/null +++ b/packages/pinball_components/lib/src/components/multiplier/cubit/multiplier_state.dart @@ -0,0 +1,56 @@ +// ignore_for_file: public_member_api_docs + +part of 'multiplier_cubit.dart'; + +enum MultiplierSpriteState { + lit, + dimmed, +} + +class MultiplierState extends Equatable { + const MultiplierState({ + required this.value, + required this.spriteState, + }); + + const MultiplierState.initial(MultiplierValue multiplierValue) + : this( + value: multiplierValue, + spriteState: MultiplierSpriteState.dimmed, + ); + + /// Current value for the [Multiplier] + final MultiplierValue value; + + /// The [MultiplierSpriteGroupComponent] current sprite state + final MultiplierSpriteState spriteState; + + MultiplierState copyWith({ + MultiplierSpriteState? spriteState, + }) { + return MultiplierState( + value: value, + spriteState: spriteState ?? this.spriteState, + ); + } + + @override + List get props => [value, spriteState]; +} + +extension MultiplierValueX on MultiplierValue { + bool equals(int value) { + switch (this) { + case MultiplierValue.x2: + return value == 2; + case MultiplierValue.x3: + return value == 3; + case MultiplierValue.x4: + return value == 4; + case MultiplierValue.x5: + return value == 5; + case MultiplierValue.x6: + return value == 6; + } + } +} diff --git a/packages/pinball_components/lib/src/components/multiplier/multiplier.dart b/packages/pinball_components/lib/src/components/multiplier/multiplier.dart new file mode 100644 index 00000000..54d02857 --- /dev/null +++ b/packages/pinball_components/lib/src/components/multiplier/multiplier.dart @@ -0,0 +1,204 @@ +// ignore_for_file: public_member_api_docs + +import 'package:flame/components.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball_components/gen/assets.gen.dart'; +import 'package:pinball_components/src/components/multiplier/cubit/multiplier_cubit.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +export 'cubit/multiplier_cubit.dart'; + +/// {@template multiplier} +/// Backlit multiplier decal displayed on the board. +/// {@endtemplate} +class Multiplier extends Component { + /// {@macro multiplier} + Multiplier._({ + required MultiplierValue value, + required Vector2 position, + required double angle, + required this.bloc, + }) : _value = value, + _position = position, + _angle = angle, + super(); + + /// {@macro multiplier} + Multiplier.x2({ + required Vector2 position, + required double angle, + }) : this._( + value: MultiplierValue.x2, + position: position, + angle: angle, + bloc: MultiplierCubit(MultiplierValue.x2), + ); + + /// {@macro multiplier} + Multiplier.x3({ + required Vector2 position, + required double angle, + }) : this._( + value: MultiplierValue.x3, + position: position, + angle: angle, + bloc: MultiplierCubit(MultiplierValue.x3), + ); + + /// {@macro multiplier} + Multiplier.x4({ + required Vector2 position, + required double angle, + }) : this._( + value: MultiplierValue.x4, + position: position, + angle: angle, + bloc: MultiplierCubit(MultiplierValue.x4), + ); + + /// {@macro multiplier} + Multiplier.x5({ + required Vector2 position, + required double angle, + }) : this._( + value: MultiplierValue.x5, + position: position, + angle: angle, + bloc: MultiplierCubit(MultiplierValue.x5), + ); + + /// {@macro multiplier} + Multiplier.x6({ + required Vector2 position, + required double angle, + }) : this._( + value: MultiplierValue.x6, + position: position, + angle: angle, + bloc: MultiplierCubit(MultiplierValue.x6), + ); + + /// Creates a [Multiplier] without any children. + /// + /// This can be used for testing [Multiplier]'s behaviors in isolation. + // TODO(alestiago): Refactor injecting bloc once the following is merged: + // https://github.com/flame-engine/flame/pull/1538 + @visibleForTesting + Multiplier.test({ + required MultiplierValue value, + required this.bloc, + }) : _value = value, + _position = Vector2.zero(), + _angle = 0; + +// TODO(ruimiguel): Consider refactoring once the following is merged: + // https://github.com/flame-engine/flame/pull/1538 + final MultiplierCubit bloc; + + final MultiplierValue _value; + final Vector2 _position; + final double _angle; + late final MultiplierSpriteGroupComponent _sprite; + + @override + void onRemove() { + bloc.close(); + super.onRemove(); + } + + @override + Future onLoad() async { + await super.onLoad(); + _sprite = MultiplierSpriteGroupComponent( + position: _position, + litAssetPath: _value.litAssetPath, + dimmedAssetPath: _value.dimmedAssetPath, + angle: _angle, + current: bloc.state, + ); + await add(_sprite); + } +} + +/// Available multiplier values. +enum MultiplierValue { + x2, + x3, + x4, + x5, + x6, +} + +extension on MultiplierValue { + String get litAssetPath { + switch (this) { + case MultiplierValue.x2: + return Assets.images.multiplier.x2.lit.keyName; + case MultiplierValue.x3: + return Assets.images.multiplier.x3.lit.keyName; + case MultiplierValue.x4: + return Assets.images.multiplier.x4.lit.keyName; + case MultiplierValue.x5: + return Assets.images.multiplier.x5.lit.keyName; + case MultiplierValue.x6: + return Assets.images.multiplier.x6.lit.keyName; + } + } + + String get dimmedAssetPath { + switch (this) { + case MultiplierValue.x2: + return Assets.images.multiplier.x2.dimmed.keyName; + case MultiplierValue.x3: + return Assets.images.multiplier.x3.dimmed.keyName; + case MultiplierValue.x4: + return Assets.images.multiplier.x4.dimmed.keyName; + case MultiplierValue.x5: + return Assets.images.multiplier.x5.dimmed.keyName; + case MultiplierValue.x6: + return Assets.images.multiplier.x6.dimmed.keyName; + } + } +} + +/// {@template multiplier_sprite_group_component} +/// A [SpriteGroupComponent] for a [Multiplier] with lit and dimmed states. +/// {@endtemplate} +@visibleForTesting +class MultiplierSpriteGroupComponent + extends SpriteGroupComponent + with HasGameRef, ParentIsA { + /// {@macro multiplier_sprite_group_component} + MultiplierSpriteGroupComponent({ + required Vector2 position, + required String litAssetPath, + required String dimmedAssetPath, + required double angle, + required MultiplierState current, + }) : _litAssetPath = litAssetPath, + _dimmedAssetPath = dimmedAssetPath, + super( + anchor: Anchor.center, + position: position, + angle: angle, + current: current.spriteState, + ); + + final String _litAssetPath; + final String _dimmedAssetPath; + + @override + Future onLoad() async { + await super.onLoad(); + parent.bloc.stream.listen((state) => current = state.spriteState); + + final sprites = { + MultiplierSpriteState.lit: + Sprite(gameRef.images.fromCache(_litAssetPath)), + MultiplierSpriteState.dimmed: + Sprite(gameRef.images.fromCache(_dimmedAssetPath)), + }; + this.sprites = sprites; + size = sprites[current]!.originalSize / 10; + } +} diff --git a/packages/pinball_components/pubspec.yaml b/packages/pinball_components/pubspec.yaml index 76607e13..37f9bd63 100644 --- a/packages/pinball_components/pubspec.yaml +++ b/packages/pinball_components/pubspec.yaml @@ -75,6 +75,11 @@ flutter: - assets/images/backboard/ - assets/images/google_word/ - assets/images/signpost/ + - assets/images/multiplier/x2/ + - assets/images/multiplier/x3/ + - assets/images/multiplier/x4/ + - assets/images/multiplier/x5/ + - assets/images/multiplier/x6/ flutter_gen: line_length: 80 diff --git a/packages/pinball_components/sandbox/lib/main.dart b/packages/pinball_components/sandbox/lib/main.dart index 96083717..1f0077fb 100644 --- a/packages/pinball_components/sandbox/lib/main.dart +++ b/packages/pinball_components/sandbox/lib/main.dart @@ -27,6 +27,7 @@ void main() { addScoreTextStories(dashbook); addBackboardStories(dashbook); addDinoWallStories(dashbook); + addMultipliersStories(dashbook); runApp(dashbook); } diff --git a/packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart b/packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart new file mode 100644 index 00000000..ae641623 --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart @@ -0,0 +1,97 @@ +import 'dart:math' as math; +import 'package:flame/input.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:sandbox/stories/ball/basic_ball_game.dart'; + +class MultipliersGame extends BallGame with KeyboardEvents { + MultipliersGame() + : super( + imagesFileNames: [ + Assets.images.multiplier.x2.lit.keyName, + Assets.images.multiplier.x2.dimmed.keyName, + Assets.images.multiplier.x3.lit.keyName, + Assets.images.multiplier.x3.dimmed.keyName, + Assets.images.multiplier.x4.lit.keyName, + Assets.images.multiplier.x4.dimmed.keyName, + Assets.images.multiplier.x5.lit.keyName, + Assets.images.multiplier.x5.dimmed.keyName, + Assets.images.multiplier.x6.lit.keyName, + Assets.images.multiplier.x6.dimmed.keyName, + ], + ); + + static const description = ''' + Shows how the Multipliers are rendered. + + - Tap anywhere on the screen to spawn a ball into the game. + - Press digits 2 to 6 for toggle state multipliers 2 to 6. +'''; + + final List multipliers = [ + Multiplier.x2( + position: Vector2(-20, 0), + angle: -15 * math.pi / 180, + ), + Multiplier.x3( + position: Vector2(20, -5), + angle: 15 * math.pi / 180, + ), + Multiplier.x4( + position: Vector2(0, -15), + angle: 0, + ), + Multiplier.x5( + position: Vector2(-10, -25), + angle: -3 * math.pi / 180, + ), + Multiplier.x6( + position: Vector2(10, -35), + angle: 8 * math.pi / 180, + ), + ]; + + @override + Future onLoad() async { + await super.onLoad(); + + camera.followVector2(Vector2.zero()); + + await addAll(multipliers); + await traceAllBodies(); + } + + @override + KeyEventResult onKeyEvent( + RawKeyEvent event, + Set keysPressed, + ) { + if (event is RawKeyDownEvent) { + var currentMultiplier = 1; + + if (event.logicalKey == LogicalKeyboardKey.digit2) { + currentMultiplier = 2; + } + if (event.logicalKey == LogicalKeyboardKey.digit3) { + currentMultiplier = 3; + } + if (event.logicalKey == LogicalKeyboardKey.digit4) { + currentMultiplier = 4; + } + if (event.logicalKey == LogicalKeyboardKey.digit5) { + currentMultiplier = 5; + } + if (event.logicalKey == LogicalKeyboardKey.digit6) { + currentMultiplier = 6; + } + + for (final multiplier in multipliers) { + multiplier.bloc.next(currentMultiplier); + } + + return KeyEventResult.handled; + } + return KeyEventResult.ignored; + } +} diff --git a/packages/pinball_components/sandbox/lib/stories/multipliers/stories.dart b/packages/pinball_components/sandbox/lib/stories/multipliers/stories.dart new file mode 100644 index 00000000..48b6da6d --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/multipliers/stories.dart @@ -0,0 +1,11 @@ +import 'package:dashbook/dashbook.dart'; +import 'package:sandbox/common/common.dart'; +import 'package:sandbox/stories/multipliers/multipliers_game.dart'; + +void addMultipliersStories(Dashbook dashbook) { + dashbook.storiesOf('Multipliers').addGame( + title: 'Multipliers', + description: MultipliersGame.description, + gameBuilder: (_) => MultipliersGame(), + ); +} diff --git a/packages/pinball_components/sandbox/lib/stories/stories.dart b/packages/pinball_components/sandbox/lib/stories/stories.dart index 9e1d44d8..d5e410b4 100644 --- a/packages/pinball_components/sandbox/lib/stories/stories.dart +++ b/packages/pinball_components/sandbox/lib/stories/stories.dart @@ -10,6 +10,7 @@ export 'flutter_forest/stories.dart'; export 'google_word/stories.dart'; export 'launch_ramp/stories.dart'; export 'layer/stories.dart'; +export 'multipliers/stories.dart'; export 'plunger/stories.dart'; export 'score_text/stories.dart'; export 'slingshot/stories.dart'; diff --git a/packages/pinball_components/sandbox/pubspec.lock b/packages/pinball_components/sandbox/pubspec.lock index 8d61da32..d2500fbe 100644 --- a/packages/pinball_components/sandbox/pubspec.lock +++ b/packages/pinball_components/sandbox/pubspec.lock @@ -15,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.8.2" + bloc: + dependency: transitive + description: + name: bloc + url: "https://pub.dartlang.org" + source: hosted + version: "8.0.3" boolean_selector: dependency: transitive description: @@ -171,7 +178,7 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.4" + version: "0.6.3" json_annotation: dependency: transitive description: @@ -199,7 +206,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.3" meta: dependency: transitive description: @@ -220,7 +227,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.0" path_provider_linux: dependency: transitive description: @@ -351,7 +358,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -386,7 +393,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.8" typed_data: dependency: transitive description: @@ -456,7 +463,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.1" very_good_analysis: dependency: "direct dev" description: diff --git a/packages/pinball_components/test/helpers/mocks.dart b/packages/pinball_components/test/helpers/mocks.dart index 2230becb..33c5670d 100644 --- a/packages/pinball_components/test/helpers/mocks.dart +++ b/packages/pinball_components/test/helpers/mocks.dart @@ -24,3 +24,5 @@ class MockGoogleLetterCubit extends Mock implements GoogleLetterCubit {} class MockSparkyBumperCubit extends Mock implements SparkyBumperCubit {} class MockDashNestBumperCubit extends Mock implements DashNestBumperCubit {} + +class MockMultiplierCubit extends Mock implements MultiplierCubit {} diff --git a/packages/pinball_components/test/src/components/golden/multipliers/x2-dimmed.png b/packages/pinball_components/test/src/components/golden/multipliers/x2-dimmed.png new file mode 100644 index 0000000000000000000000000000000000000000..ca2d8bf1dc5499ec4fad3e62c3d99656f232b2b1 GIT binary patch literal 23391 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 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/test/src/components/golden/multipliers/x2-lit.png b/packages/pinball_components/test/src/components/golden/multipliers/x2-lit.png new file mode 100644 index 0000000000000000000000000000000000000000..94001e27894860b1a666dd63befd21a8b2f5b5e1 GIT binary patch literal 23847 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 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/test/src/components/golden/multipliers/x3-lit.png b/packages/pinball_components/test/src/components/golden/multipliers/x3-lit.png new file mode 100644 index 0000000000000000000000000000000000000000..f2f8417802af05b453e1280af157ef5413dd7813 GIT binary patch literal 24555 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 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/test/src/components/golden/multipliers/x4-lit.png b/packages/pinball_components/test/src/components/golden/multipliers/x4-lit.png new file mode 100644 index 0000000000000000000000000000000000000000..b4918e623700c71b96438d5499416b8efac76343 GIT binary patch literal 25722 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 PAi8&Vh=19xh_n9(2}o@< literal 0 HcmV?d00001 diff --git a/packages/pinball_components/test/src/components/golden/multipliers/x5-dimmed.png b/packages/pinball_components/test/src/components/golden/multipliers/x5-dimmed.png new file mode 100644 index 0000000000000000000000000000000000000000..2bbbf1efa03169845774358bd4c9d93d3d81d615 GIT binary patch literal 24980 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 H==c8yGYtM8 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/test/src/components/golden/multipliers/x5-lit.png b/packages/pinball_components/test/src/components/golden/multipliers/x5-lit.png new file mode 100644 index 0000000000000000000000000000000000000000..5e750af83293f06ab3e0980fb42a0240061aafcc GIT binary patch literal 26830 zcmeHwX;f3^+IDJ1&?=~{(jtRZQv_6O1qlR5ZL1tXpdfb9+Eu4OPf4HDRD2?5?MiL<({PWH=m~8lv zK>x9(HMe<91byL0DFyfb0X=vWmraFo;&6hz7Og!_yE@a#v}w z7tBPfP(U7l33?TayP&mLg#xq|pb=f+!ha!$md-r92U*z*09+N6U$8z}As47Kpw9gF zbOzKG$p3|h@j=X}EUg8zJfdDTF_A0QmKP7vvewVnC+Y863ySiSqp`rzadWDEQgVs- zSUe>SnCK-|YH{Qn#iHl__{f#m8^4yHto1e`Aawe=k<4*=W+Hr|A3fEJA1{#!CNY$1 z^sxH!&-|wS*KMRXn}3jBgOM*BvfVHjSBmwrZJ{t+BagcW2OHPO#_%Prbc_~CNRvo~ zwE8ZUmL2l_9@7cP4S(HdO5ZD=^FW4kriQ6`&;2MgudPem?4C$AL7Fp*&C~=uDN8ij zk48&J`~*UGjM<2gw%Da2_-<*Ml3S*0Hl?ktH*B^qy|2xoR^`kIPIsNQtvdcy{G3v(mYFzsqLh=B7&SjL+(j&HE-4q6iXO*(ekWfj zc{{xMwYYb@#IJ~hqT{n0QJkV0$9zPq)=V=d9$5yn2HC5f4fp%eY1rH$2JqKF7BR4H6jT=w~$MBuH93P(^y)fwFWme22u(}p$< z4h1Q93e*S3m@;)SF~3(NT3P$u>#ULE@i@dV93X(CF|NecO%gECPpR31!c@cH;j_UL z^^Kcf*DrQU%0tB^?(h@y#il31kIhaFT^Wo(&11PyQLVDKHw{~NXh!l9zs*=i)hGP# z=@$RUOR?29#Y+*fM?9Z`QA5e(xHfjzEsBP_Vt|_?CJ9Q)Er3Cc#pN2_#=)s;yai;a zKRL68f3W~PKQSN!mO=A$;f!hRR}Z`oUvM^}x>cwcv+tY2DKEEu`SKIdYt`y^?(JmR zFMeBpJnB(fys-{{=&R!fmuXw6U%iZ>jdZ3@5ylGtfJTN@>;Jm-jNq=bQ5I*c;Ca#x z?d&mK-c=GdIPzZxy+a=U9LHFW%A)|+kUIb&AO|u(G;)8YLOw(lbl1}NZ*@J_=u5m= z!}4xTA&DpUKy7WRUHJwb$~GLQ%hrV&eegp_Qj)HcHXK@BfBM!FD)a06(i)euUCOAN zib1&^g{tboIu<@dBMT1Jsbfm5EvnG`B~aJKgYH)!TE)+w-d+lrx`P+Rn*@u`W$^0R zOH}xtGHlU9(+orgKlyz7SvaiQ`0lt(n3ZON7t|;()SowirmC1n)v$*fk?h8LoRg}` z(0qM6PTvM$NolpzY`uh_b

    #1SWefXtFZGtW4p=`{RVAnarQ!uL&B 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 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/test/src/components/golden/multipliers/x6-lit.png b/packages/pinball_components/test/src/components/golden/multipliers/x6-lit.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5edc1099e97e53050ce2f230a97040707c71fa GIT binary patch literal 26854 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 C!cOr3 literal 0 HcmV?d00001 diff --git a/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart b/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart new file mode 100644 index 00000000..35ed652e --- /dev/null +++ b/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart @@ -0,0 +1,118 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/pinball_components.dart'; + +void main() { + group( + 'MultiplierCubit', + () { + blocTest( + "emits [lit] when 'next' on x2 dimmed with x2 multiplier value", + build: () => MultiplierCubit(MultiplierValue.x2), + act: (bloc) => bloc.next(2), + expect: () => [ + isA() + ..having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), + ], + ); + + blocTest( + "emits [lit] when 'next' on x3 dimmed with x3 multiplier value", + build: () => MultiplierCubit(MultiplierValue.x3), + act: (bloc) => bloc.next(3), + expect: () => [ + isA() + ..having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), + ], + ); + + blocTest( + "emits [lit] when 'next' on x4 dimmed with x4 multiplier value", + build: () => MultiplierCubit(MultiplierValue.x4), + act: (bloc) => bloc.next(4), + expect: () => [ + isA() + ..having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), + ], + ); + + blocTest( + "emits [lit] when 'next' on x5 dimmed with x5 multiplier value", + build: () => MultiplierCubit(MultiplierValue.x5), + act: (bloc) => bloc.next(5), + expect: () => [ + isA() + ..having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), + ], + ); + + blocTest( + "emits [lit] when 'next' on x6 dimmed with x6 multiplier value", + build: () => MultiplierCubit(MultiplierValue.x6), + act: (bloc) => bloc.next(6), + expect: () => [ + isA() + ..having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), + ], + ); + + blocTest( + "emits [dimmed] when 'next' on lit with different multiplier value", + build: () => MultiplierCubit(MultiplierValue.x2), + seed: () => MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.lit, + ), + act: (bloc) => bloc.next(3), + expect: () => [ + isA() + ..having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.dimmed, + ), + ], + ); + + blocTest( + "emits nothing when 'next' on lit with same multiplier value", + build: () => MultiplierCubit(MultiplierValue.x2), + seed: () => MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.lit, + ), + act: (bloc) => bloc.next(2), + expect: () => [], + ); + + blocTest( + "emits nothing when 'next' on dimmed with different multiplier value", + build: () => MultiplierCubit(MultiplierValue.x2), + act: (bloc) => bloc.next(3), + expect: () => [], + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_state_test.dart b/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_state_test.dart new file mode 100644 index 00000000..9789d7c5 --- /dev/null +++ b/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_state_test.dart @@ -0,0 +1,75 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/src/pinball_components.dart'; + +void main() { + group('MultiplierState', () { + test('supports value equality', () { + expect( + MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.lit, + ), + equals( + MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.lit, + ), + ), + ); + }); + + group('constructor', () { + test('can be instantiated', () { + expect( + MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.lit, + ), + isNotNull, + ); + }); + }); + + group('copyWith', () { + test( + 'copies correctly ' + 'when no argument specified', + () { + const multiplierState = MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.lit, + ); + expect( + multiplierState.copyWith(), + equals(multiplierState), + ); + }, + ); + + test( + 'copies correctly ' + 'when all arguments specified', + () { + const multiplierState = MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.lit, + ); + final otherMultiplierState = MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.dimmed, + ); + expect(multiplierState, isNot(equals(otherMultiplierState))); + + expect( + multiplierState.copyWith( + spriteState: MultiplierSpriteState.dimmed, + ), + equals(otherMultiplierState), + ); + }, + ); + }); + }); +} diff --git a/packages/pinball_components/test/src/components/multiplier/multiplier_test.dart b/packages/pinball_components/test/src/components/multiplier/multiplier_test.dart new file mode 100644 index 00000000..edc2735f --- /dev/null +++ b/packages/pinball_components/test/src/components/multiplier/multiplier_test.dart @@ -0,0 +1,517 @@ +// ignore_for_file: cascade_invocations, prefer_const_constructors + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame/components.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; + +import '../../../helpers/helpers.dart'; + +void main() { + final bloc = MockMultiplierCubit(); + + group('Multiplier', () { + TestWidgetsFlutterBinding.ensureInitialized(); + final assets = [ + Assets.images.multiplier.x2.lit.keyName, + Assets.images.multiplier.x2.dimmed.keyName, + Assets.images.multiplier.x3.lit.keyName, + Assets.images.multiplier.x3.dimmed.keyName, + Assets.images.multiplier.x4.lit.keyName, + Assets.images.multiplier.x4.dimmed.keyName, + Assets.images.multiplier.x5.lit.keyName, + Assets.images.multiplier.x5.dimmed.keyName, + Assets.images.multiplier.x6.lit.keyName, + Assets.images.multiplier.x6.dimmed.keyName, + ]; + final flameTester = FlameTester(() => TestGame(assets)); + + flameTester.test('"x2" loads correctly', (game) async { + final multiplier = Multiplier.x2( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + expect(game.contains(multiplier), isTrue); + }); + + flameTester.test('"x3" loads correctly', (game) async { + final multiplier = Multiplier.x3( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + expect(game.contains(multiplier), isTrue); + }); + + flameTester.test('"x4" loads correctly', (game) async { + final multiplier = Multiplier.x4( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + expect(game.contains(multiplier), isTrue); + }); + + flameTester.test('"x5" loads correctly', (game) async { + final multiplier = Multiplier.x5( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + expect(game.contains(multiplier), isTrue); + }); + + flameTester.test('"x6" loads correctly', (game) async { + final multiplier = Multiplier.x6( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + expect(game.contains(multiplier), isTrue); + }); + + group('renders correctly', () { + group('x2', () { + const multiplierValue = MultiplierValue.x2; + + flameTester.testGameWidget( + 'lit when bloc state is lit', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.lit, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.lit, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x2-lit.png'), + ); + }, + ); + + flameTester.testGameWidget( + 'dimmed when bloc state is dimmed', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.dimmed, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.dimmed, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x2-dimmed.png'), + ); + }, + ); + }); + + group('x3', () { + const multiplierValue = MultiplierValue.x3; + + flameTester.testGameWidget( + 'lit when bloc state is lit', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.lit, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.lit, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x3-lit.png'), + ); + }, + ); + + flameTester.testGameWidget( + 'dimmed when bloc state is dimmed', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.dimmed, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.dimmed, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x3-dimmed.png'), + ); + }, + ); + }); + + group('x4', () { + const multiplierValue = MultiplierValue.x4; + + flameTester.testGameWidget( + 'lit when bloc state is lit', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.lit, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.lit, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x4-lit.png'), + ); + }, + ); + + flameTester.testGameWidget( + 'dimmed when bloc state is dimmed', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.dimmed, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.dimmed, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x4-dimmed.png'), + ); + }, + ); + }); + + group('x5', () { + const multiplierValue = MultiplierValue.x5; + + flameTester.testGameWidget( + 'lit when bloc state is lit', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.lit, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.lit, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x5-lit.png'), + ); + }, + ); + + flameTester.testGameWidget( + 'dimmed when bloc state is dimmed', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.dimmed, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.dimmed, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x5-dimmed.png'), + ); + }, + ); + }); + + group('x6', () { + const multiplierValue = MultiplierValue.x6; + + flameTester.testGameWidget( + 'lit when bloc state is lit', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.lit, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.lit, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x6-lit.png'), + ); + }, + ); + + flameTester.testGameWidget( + 'dimmed when bloc state is dimmed', + setUp: (game, tester) async { + await game.images.loadAll(assets); + + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: multiplierValue, + spriteState: MultiplierSpriteState.dimmed, + ), + ); + + final multiplier = Multiplier.test( + value: multiplierValue, + bloc: bloc, + ); + await game.ensureAdd(multiplier); + await tester.pump(); + + game.camera.followVector2(Vector2.zero()); + }, + verify: (game, tester) async { + expect( + game + .descendants() + .whereType() + .first + .current, + MultiplierSpriteState.dimmed, + ); + + await expectLater( + find.byGame(), + matchesGoldenFile('../golden/multipliers/x6-dimmed.png'), + ); + }, + ); + }); + }); + + flameTester.test('closes bloc when removed', (game) async { + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.dimmed, + ), + ); + when(bloc.close).thenAnswer((_) async {}); + final multiplier = Multiplier.test(value: MultiplierValue.x2, bloc: bloc); + + await game.ensureAdd(multiplier); + game.remove(multiplier); + await game.ready(); + + verify(bloc.close).called(1); + }); + }); +} diff --git a/test/game/components/multipliers/behaviors/multipliers_behavior_test.dart b/test/game/components/multipliers/behaviors/multipliers_behavior_test.dart new file mode 100644 index 00000000..a4f3502c --- /dev/null +++ b/test/game/components/multipliers/behaviors/multipliers_behavior_test.dart @@ -0,0 +1,133 @@ +// ignore_for_file: cascade_invocations, prefer_const_constructors + +import 'dart:async'; + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockingjay/mockingjay.dart'; +import 'package:pinball/game/components/multipliers/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.multiplier.x2.lit.keyName, + Assets.images.multiplier.x2.dimmed.keyName, + Assets.images.multiplier.x3.lit.keyName, + Assets.images.multiplier.x3.dimmed.keyName, + Assets.images.multiplier.x4.lit.keyName, + Assets.images.multiplier.x4.dimmed.keyName, + Assets.images.multiplier.x5.lit.keyName, + Assets.images.multiplier.x5.dimmed.keyName, + Assets.images.multiplier.x6.lit.keyName, + Assets.images.multiplier.x6.dimmed.keyName, + ]; + + group('MultipliersBehavior', () { + late GameBloc gameBloc; + + setUp(() { + registerFallbackValue(MockComponent()); + gameBloc = MockGameBloc(); + whenListen( + gameBloc, + const Stream.empty(), + initialState: const GameState.initial(), + ); + }); + + final flameBlocTester = FlameBlocTester( + gameBuilder: EmptyPinballTestGame.new, + blocBuilder: () => gameBloc, + assets: assets, + ); + + group('listenWhen', () { + test('is true when the multiplier has changed', () { + final state = GameState( + score: 10, + multiplier: 2, + rounds: 0, + bonusHistory: const [], + ); + + final previous = GameState.initial(); + expect( + MultipliersBehavior().listenWhen(previous, state), + isTrue, + ); + }); + + test('is false when the multiplier state is the same', () { + final state = GameState( + score: 10, + multiplier: 1, + rounds: 0, + bonusHistory: const [], + ); + + final previous = GameState.initial(); + expect( + MultipliersBehavior().listenWhen(previous, state), + isFalse, + ); + }); + }); + + group('onNewState', () { + flameBlocTester.testGameWidget( + "calls 'next' once per each multiplier when GameBloc emit state", + setUp: (game, tester) async { + final behavior = MultipliersBehavior(); + final parent = Multipliers.test(); + final multiplierX2Cubit = MockMultiplierCubit(); + final multiplierX3Cubit = MockMultiplierCubit(); + final multipliers = [ + Multiplier.test( + value: MultiplierValue.x2, + bloc: multiplierX2Cubit, + ), + Multiplier.test( + value: MultiplierValue.x3, + bloc: multiplierX3Cubit, + ), + ]; + + whenListen( + multiplierX2Cubit, + const Stream.empty(), + initialState: MultiplierState.initial(MultiplierValue.x2), + ); + when(() => multiplierX2Cubit.next(any())).thenAnswer((_) async {}); + + whenListen( + multiplierX3Cubit, + const Stream.empty(), + initialState: MultiplierState.initial(MultiplierValue.x2), + ); + when(() => multiplierX3Cubit.next(any())).thenAnswer((_) async {}); + + await parent.addAll(multipliers); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + + await tester.pump(); + + behavior.onNewState( + GameState.initial().copyWith(multiplier: 2), + ); + + for (final multiplier in multipliers) { + verify( + () => multiplier.bloc.next(any()), + ).called(1); + } + }, + ); + }); + }); +} diff --git a/test/game/components/multipliers/multipliers_test.dart b/test/game/components/multipliers/multipliers_test.dart new file mode 100644 index 00000000..6b2d95a6 --- /dev/null +++ b/test/game/components/multipliers/multipliers_test.dart @@ -0,0 +1,63 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.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.multiplier.x2.lit.keyName, + Assets.images.multiplier.x2.dimmed.keyName, + Assets.images.multiplier.x3.lit.keyName, + Assets.images.multiplier.x3.dimmed.keyName, + Assets.images.multiplier.x4.lit.keyName, + Assets.images.multiplier.x4.dimmed.keyName, + Assets.images.multiplier.x5.lit.keyName, + Assets.images.multiplier.x5.dimmed.keyName, + Assets.images.multiplier.x6.lit.keyName, + Assets.images.multiplier.x6.dimmed.keyName, + ]; + + late GameBloc gameBloc; + + setUp(() { + gameBloc = GameBloc(); + }); + + final flameBlocTester = FlameBlocTester( + gameBuilder: EmptyPinballTestGame.new, + blocBuilder: () => gameBloc, + assets: assets, + ); + + group('Multipliers', () { + flameBlocTester.testGameWidget( + 'loads correctly', + setUp: (game, tester) async { + final multipliersGroup = Multipliers(); + await game.ensureAdd(multipliersGroup); + + expect(game.contains(multipliersGroup), isTrue); + }, + ); + + group('loads', () { + flameBlocTester.testGameWidget( + 'five Multiplier', + setUp: (game, tester) async { + final multipliersGroup = Multipliers(); + await game.ensureAdd(multipliersGroup); + + expect( + multipliersGroup.descendants().whereType().length, + equals(5), + ); + }, + ); + }); + }); +} diff --git a/test/game/pinball_game_test.dart b/test/game/pinball_game_test.dart index d614f709..a7240286 100644 --- a/test/game/pinball_game_test.dart +++ b/test/game/pinball_game_test.dart @@ -1,5 +1,6 @@ // ignore_for_file: cascade_invocations +import 'package:bloc_test/bloc_test.dart'; import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flame_test/flame_test.dart'; @@ -54,6 +55,16 @@ void main() { Assets.images.launchRamp.ramp.keyName, Assets.images.launchRamp.foregroundRailing.keyName, Assets.images.launchRamp.backgroundRailing.keyName, + Assets.images.multiplier.x2.lit.keyName, + Assets.images.multiplier.x2.dimmed.keyName, + Assets.images.multiplier.x3.lit.keyName, + Assets.images.multiplier.x3.dimmed.keyName, + Assets.images.multiplier.x4.lit.keyName, + Assets.images.multiplier.x4.dimmed.keyName, + Assets.images.multiplier.x5.lit.keyName, + Assets.images.multiplier.x5.dimmed.keyName, + Assets.images.multiplier.x6.lit.keyName, + Assets.images.multiplier.x6.dimmed.keyName, Assets.images.plunger.plunger.keyName, Assets.images.plunger.rocket.keyName, Assets.images.signpost.inactive.keyName, @@ -94,6 +105,17 @@ void main() { Assets.images.sparky.bumper.c.inactive.keyName, ]; + late GameBloc gameBloc; + + setUp(() { + gameBloc = MockGameBloc(); + whenListen( + gameBloc, + const Stream.empty(), + initialState: const GameState.initial(), + ); + }); + final flameTester = FlameTester( () => PinballTestGame(assets: assets), ); @@ -101,11 +123,16 @@ void main() { () => DebugPinballTestGame(assets: assets), ); + final flameBlocTester = FlameBlocTester( + gameBuilder: () => PinballTestGame(assets: assets), + blocBuilder: () => gameBloc, + ); + group('PinballGame', () { group('components', () { // TODO(alestiago): tests that Blueprints get added once the Blueprint // class is removed. - flameTester.test( + flameBlocTester.test( 'has only one Drain', (game) async { await game.ready(); @@ -116,11 +143,10 @@ void main() { }, ); - flameTester.test( + flameBlocTester.test( 'has only one BottomGroup', (game) async { await game.ready(); - expect( game.children.whereType().length, equals(1), @@ -128,7 +154,7 @@ void main() { }, ); - flameTester.test( + flameBlocTester.test( 'has only one Plunger', (game) async { await game.ready(); @@ -139,7 +165,7 @@ void main() { }, ); - flameTester.test('has one FlutterForest', (game) async { + flameBlocTester.test('has one FlutterForest', (game) async { await game.ready(); expect( game.children.whereType().length, @@ -147,7 +173,7 @@ void main() { ); }); - flameTester.test( + flameBlocTester.test( 'one GoogleWord', (game) async { await game.ready(); diff --git a/test/helpers/mocks.dart b/test/helpers/mocks.dart index 14a286e2..1578c3e0 100644 --- a/test/helpers/mocks.dart +++ b/test/helpers/mocks.dart @@ -64,6 +64,8 @@ class MockFilter extends Mock implements Filter {} class MockFixture extends Mock implements Fixture {} +class MockComponent extends Mock implements Component {} + class MockComponentSet extends Mock implements ComponentSet {} class MockDashNestBumper extends Mock implements DashNestBumper {} @@ -86,3 +88,9 @@ class MockGameFlowController extends Mock implements GameFlowController {} class MockAndroidBumper extends Mock implements AndroidBumper {} class MockSparkyBumper extends Mock implements SparkyBumper {} + +class MockMultiplier extends Mock implements Multiplier {} + +class MockMultipliersGroup extends Mock implements Multipliers {} + +class MockMultiplierCubit extends Mock implements MultiplierCubit {}