From a61df839e17eec3d813b5d575ca57bb48a8188d6 Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Fri, 8 Apr 2022 17:20:24 -0300 Subject: [PATCH] feat: finishing score text effects --- .../components/score_effect_controller.dart | 54 ++------ lib/gen/assets.gen.dart | 5 - .../lib/src/components/score_text_effect.dart | 8 +- .../components/score_text_effects_test.dart | 8 +- .../score_effect_controller_test.dart | 115 ++++++++++++++++++ 5 files changed, 131 insertions(+), 59 deletions(-) create mode 100644 test/game/components/score_effect_controller_test.dart diff --git a/lib/game/components/score_effect_controller.dart b/lib/game/components/score_effect_controller.dart index 73ae4a21..1c996ccd 100644 --- a/lib/game/components/score_effect_controller.dart +++ b/lib/game/components/score_effect_controller.dart @@ -1,18 +1,18 @@ -import 'dart:async'; import 'dart:math'; import 'package:flame/components.dart'; -import 'package:flame/effects.dart'; import 'package:flame_bloc/flame_bloc.dart'; -import 'package:flutter/material.dart'; import 'package:pinball/flame/flame.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -/// +/// {@template score_effect_controller} +/// A [ComponentController] responsible for adding [ScoreTextEffect]s +/// on the game screen when the user has earned more points. +/// {@endtemplate} class ScoreEffectController extends ComponentController with BlocComponent { - /// + /// {@macro score_effect_controller} ScoreEffectController(PinballGame component) : super(component); int _lastScore = 0; @@ -32,11 +32,11 @@ class ScoreEffectController extends ComponentController final newScore = state.score - _lastScore; component.add( - _Text( + ScoreTextEffect( text: newScore.toString(), position: Vector2( - _noise(), - _noise() + (-BoardDimensions.bounds.topCenter.dy + 10), + _noise(), + _noise() + (-BoardDimensions.bounds.topCenter.dy + 10), ), ), ); @@ -44,41 +44,3 @@ class ScoreEffectController extends ComponentController _lastScore = state.score; } } - -class _Text extends TextComponent { - _Text({ - required String text, - required Vector2 position, - }) : super( - text: text, - position: position, - anchor: Anchor.center, - priority: 100, - ); - late final Effect _effect; - - @override - Future onLoad() async { - textRenderer = TextPaint( - style: const TextStyle(color: Colors.pink, fontSize: 4), - ); - - unawaited( - add( - _effect = MoveEffect.by( - Vector2(0, -5), - EffectController(duration: 1), - ), - ), - ); - } - - @override - void update(double dt) { - super.update(dt); - - if (_effect.controller.completed) { - removeFromParent(); - } - } -} diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index 90013646..b3b964f3 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -3,8 +3,6 @@ /// FlutterGen /// ***************************************************** -// ignore_for_file: directives_ordering,unnecessary_import - import 'package:flutter/widgets.dart'; class $AssetsImagesGen { @@ -17,11 +15,8 @@ class $AssetsImagesGen { class $AssetsImagesComponentsGen { const $AssetsImagesComponentsGen(); - /// File path: assets/images/components/background.png AssetGenImage get background => const AssetGenImage('assets/images/components/background.png'); - - /// File path: assets/images/components/plunger.png AssetGenImage get plunger => const AssetGenImage('assets/images/components/plunger.png'); } diff --git a/packages/pinball_components/lib/src/components/score_text_effect.dart b/packages/pinball_components/lib/src/components/score_text_effect.dart index 91b99c61..c677f445 100644 --- a/packages/pinball_components/lib/src/components/score_text_effect.dart +++ b/packages/pinball_components/lib/src/components/score_text_effect.dart @@ -11,7 +11,6 @@ import 'package:pinball_components/gen/fonts.gen.dart'; /// once its animation is completed /// {@endtemplate} class ScoreTextEffect extends TextComponent { - /// {@macro score_text_effect} ScoreTextEffect({ required String text, @@ -24,6 +23,7 @@ class ScoreTextEffect extends TextComponent { priority: 100, ); late final Effect _effect; + /// The [text] [Color] final Color color; @@ -31,9 +31,9 @@ class ScoreTextEffect extends TextComponent { Future onLoad() async { textRenderer = TextPaint( style: TextStyle( - fontFamily: 'packages/pinball_components/${FontFamily.pixeloidMono}', - color: color, - fontSize: 4, + fontFamily: 'packages/pinball_components/${FontFamily.pixeloidMono}', + color: color, + fontSize: 4, ), ); diff --git a/packages/pinball_components/test/src/components/score_text_effects_test.dart b/packages/pinball_components/test/src/components/score_text_effects_test.dart index 169437d1..00d3e2d2 100644 --- a/packages/pinball_components/test/src/components/score_text_effects_test.dart +++ b/packages/pinball_components/test/src/components/score_text_effects_test.dart @@ -26,8 +26,8 @@ void main() { }, verify: (game, tester) async { await expectLater( - find.byGame(), - matchesGoldenFile('golden/score_text_effect/render.png'), + find.byGame(), + matchesGoldenFile('golden/score_text_effect/render.png'), ); }, ); @@ -49,8 +49,8 @@ void main() { }, verify: (game, tester) async { await expectLater( - find.byGame(), - matchesGoldenFile('golden/score_text_effect/movement.png'), + find.byGame(), + matchesGoldenFile('golden/score_text_effect/movement.png'), ); }, ); diff --git a/test/game/components/score_effect_controller_test.dart b/test/game/components/score_effect_controller_test.dart new file mode 100644 index 00000000..93a1df1e --- /dev/null +++ b/test/game/components/score_effect_controller_test.dart @@ -0,0 +1,115 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame/components.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + group('ScoreEffectController', () { + late ScoreEffectController controller; + late PinballGame game; + + setUpAll(() { + registerFallbackValue(Component()); + }); + + setUp(() { + game = MockPinballGame(); + when(() => game.add(any())).thenAnswer((_) async {}); + + controller = ScoreEffectController(game); + }); + + group('listenWhen', () { + test('returns true when the user has earned points', () { + const previous = GameState.initial(); + const current = GameState( + score: 10, + balls: 3, + activatedBonusLetters: [], + bonusHistory: [], + activatedDashNests: {}, + ); + expect(controller.listenWhen(previous, current), isTrue); + }); + + test( + 'returns true when the user has earned points and there was no ' + 'previous state', + () { + const current = GameState( + score: 10, + balls: 3, + activatedBonusLetters: [], + bonusHistory: [], + activatedDashNests: {}, + ); + expect(controller.listenWhen(null, current), isTrue); + }, + ); + + test( + 'returns false when no points were earned', + () { + const current = GameState.initial(); + const previous = GameState.initial(); + expect(controller.listenWhen(previous, current), isFalse); + }, + ); + }); + + group('onNewState', () { + test( + 'adds a ScoreTextEffect with the correct score for the ' + 'first time', + () { + const state = GameState( + score: 10, + balls: 3, + activatedBonusLetters: [], + bonusHistory: [], + activatedDashNests: {}, + ); + + controller.onNewState(state); + + final effect = verify(() => game.add(captureAny())).captured.first + as ScoreTextEffect; + + expect(effect.text, equals('10')); + }, + ); + + test('adds a ScoreTextEffect with the correct score', () { + controller.onNewState( + const GameState( + score: 10, + balls: 3, + activatedBonusLetters: [], + bonusHistory: [], + activatedDashNests: {}, + ), + ); + + controller.onNewState( + const GameState( + score: 14, + balls: 3, + activatedBonusLetters: [], + bonusHistory: [], + activatedDashNests: {}, + ), + ); + + final effect = verify(() => game.add(captureAny())).captured.last + as ScoreTextEffect; + + expect(effect.text, equals('4')); + }); + }); + }); +}