diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 0ace3bf6..c88b7c9a 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -3,12 +3,12 @@ export 'board.dart'; export 'camera_controller.dart'; export 'controlled_ball.dart'; export 'controlled_flipper.dart'; -export 'controlled_multipliers.dart'; export 'controlled_plunger.dart'; 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'; export 'wall.dart'; diff --git a/lib/game/components/controlled_multipliers.dart b/lib/game/components/controlled_multipliers.dart deleted file mode 100644 index 6df9dee5..00000000 --- a/lib/game/components/controlled_multipliers.dart +++ /dev/null @@ -1,99 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'dart:math' as math; -import 'package:flame/components.dart'; -import 'package:flame_bloc/flame_bloc.dart'; -import 'package:flutter/material.dart'; -import 'package:pinball/game/game.dart'; -import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; - -/// {@template multipliers_group_component} -/// A [SpriteGroupComponent] for the multiplier over the board. -/// {@endtemplate} -class Multipliers extends Component - with Controls, HasGameRef { - /// {@macro multipliers_group_component} - Multipliers() - : x2multiplier = Multiplier( - value: MultiplierValue.x2, - position: Vector2(-19.5, -2), - rotation: -15 * math.pi / 180, - ), - x3multiplier = Multiplier( - value: MultiplierValue.x3, - position: Vector2(13, -9.4), - rotation: 15 * math.pi / 180, - ), - x4multiplier = Multiplier( - value: MultiplierValue.x4, - position: Vector2(0, -21.2), - ), - x5multiplier = Multiplier( - value: MultiplierValue.x5, - position: Vector2(-8.5, -28), - rotation: -3 * math.pi / 180, - ), - x6multiplier = Multiplier( - value: MultiplierValue.x6, - position: Vector2(10, -30.7), - rotation: 8 * math.pi / 180, - ), - super() { - controller = MultipliersController(this); - } - - final Multiplier x2multiplier; - - final Multiplier x3multiplier; - - final Multiplier x4multiplier; - - final Multiplier x5multiplier; - - final Multiplier x6multiplier; - - @override - Future onLoad() async { - await super.onLoad(); - - await addAll([ - x2multiplier, - x3multiplier, - x4multiplier, - x5multiplier, - x6multiplier, - ]); - } -} - -/// {@template multipliers_controller} -/// Controller attached to a [Multipliers] that handles its game related -/// logic. -/// {@endtemplate} -@visibleForTesting -class MultipliersController extends ComponentController - with BlocComponent, HasGameRef { - /// {@macro multipliers_controller} - MultipliersController(Multipliers multipliersGroup) : super(multipliersGroup); - - @override - bool listenWhen(GameState? previousState, GameState newState) { - // TODO(ruimiguel): use here GameState.multiplier when merged - // https://github.com/VGVentures/pinball/pull/213. - return previousState?.score != newState.score; - } - - @override - void onNewState(GameState state) { - // TODO(ruimiguel): use here GameState.multiplier when merged - // https://github.com/VGVentures/pinball/pull/213. - final currentMultiplier = state.score.bitLength % 6 + 1; - - component.x2multiplier.toggle(currentMultiplier); - component.x3multiplier.toggle(currentMultiplier); - component.x4multiplier.toggle(currentMultiplier); - component.x5multiplier.toggle(currentMultiplier); - component.x6multiplier.toggle(currentMultiplier); - } -} diff --git a/lib/game/components/multipliers/multipliers.dart b/lib/game/components/multipliers/multipliers.dart index 015d210f..be5579f2 100644 --- a/lib/game/components/multipliers/multipliers.dart +++ b/lib/game/components/multipliers/multipliers.dart @@ -1,7 +1,6 @@ -// ignore_for_file: public_member_api_docs - 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'; @@ -40,4 +39,10 @@ class Multipliers extends Component { MultipliersBehavior(), ], ); + + /// Creates a [Multipliers] without any children. + /// + /// This can be used for testing [Multipliers]'s behaviors in isolation. + @visibleForTesting + Multipliers.test(); } 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..5bf5ad7b --- /dev/null +++ b/test/game/components/multipliers/behaviors/multipliers_behavior_test.dart @@ -0,0 +1,64 @@ +// ignore_for_file: cascade_invocations, prefer_const_constructors + +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 '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('MultipliersBehaviors', () { + late GameBloc gameBloc; + + setUp(() { + gameBloc = MockGameBloc(); + whenListen( + gameBloc, + const Stream.empty(), + initialState: const GameState.initial(), + ); + }); + + final flameBlocTester = FlameBlocTester( + gameBuilder: EmptyPinballTestGame.new, + blocBuilder: () => gameBloc, + ); + + flameBlocTester.testGameWidget( + 'calls toggle once per each multiplier when GameBloc emit state', + setUp: (game, tester) async { + final behavior = MultipliersBehavior(); + final parent = Multipliers.test(); + final multipliers = [ + MockMultiplier(), + MockMultiplier(), + MockMultiplier(), + MockMultiplier(), + MockMultiplier(), + ]; + whenListen( + gameBloc, + const Stream.empty(), + initialState: GameState.initial(), + ); + + await parent.addAll(multipliers); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + + await tester.pump(); + + for (final multiplier in multipliers) { + verify( + () => multiplier.bloc.toggle(1), + ).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), + ); + }, + ); + }); + }); +}