From 1e894a5639b2988aeda0181131f75adaf2b78d03 Mon Sep 17 00:00:00 2001 From: arturplaczek Date: Tue, 26 Apr 2022 13:37:41 +0200 Subject: [PATCH] fix: apply code review --- lib/game/view/widgets/bonus_animation.dart | 88 +++++++++++++++---- lib/game/view/widgets/game_hud.dart | 4 +- lib/game/view/widgets/score_view.dart | 8 +- lib/game/view/widgets/widgets.dart | 2 +- .../view/widgets/bonus_animation_test.dart | 10 +-- test/game/view/widgets/game_hud_test.dart | 2 +- 6 files changed, 82 insertions(+), 32 deletions(-) diff --git a/lib/game/view/widgets/bonus_animation.dart b/lib/game/view/widgets/bonus_animation.dart index fb6f2c53..cd6854db 100644 --- a/lib/game/view/widgets/bonus_animation.dart +++ b/lib/game/view/widgets/bonus_animation.dart @@ -1,19 +1,23 @@ -// ignore_for_file: public_member_api_docs - import 'package:flame/flame.dart'; import 'package:flame/sprite.dart'; -import 'package:flame/widgets.dart'; import 'package:flutter/material.dart' hide Image; import 'package:pinball/gen/assets.gen.dart'; +import 'package:pinball_flame/pinball_flame.dart'; -class BonusAnimation extends StatelessWidget { +/// {@template bonus_animation} +/// [Widget] that displays the animation. +/// {@endtemplate} +class BonusAnimation extends StatefulWidget { + /// {@macro bonus_animation} const BonusAnimation._( - this.imagePath, { + String imagePath, { VoidCallback? onCompleted, Key? key, - }) : _onCompleted = onCompleted, + }) : _imagePath = imagePath, + _onCompleted = onCompleted, super(key: key); + /// [Widget] that displays the dash nest animation. BonusAnimation.dashNest({ Key? key, VoidCallback? onCompleted, @@ -23,6 +27,7 @@ class BonusAnimation extends StatelessWidget { key: key, ); + /// [Widget] that displays the sparky turbo charge animation. BonusAnimation.sparkyTurboCharge({ Key? key, VoidCallback? onCompleted, @@ -32,6 +37,7 @@ class BonusAnimation extends StatelessWidget { key: key, ); + /// [Widget] that displays the dino chomp animation. BonusAnimation.dinoChomp({ Key? key, VoidCallback? onCompleted, @@ -41,6 +47,7 @@ class BonusAnimation extends StatelessWidget { key: key, ); + /// [Widget] that displays the android spaceship animation. BonusAnimation.androidSpaceship({ Key? key, VoidCallback? onCompleted, @@ -50,6 +57,7 @@ class BonusAnimation extends StatelessWidget { key: key, ); + /// [Widget] that displays the google word animation. BonusAnimation.googleWord({ Key? key, VoidCallback? onCompleted, @@ -59,29 +67,64 @@ class BonusAnimation extends StatelessWidget { key: key, ); - final String imagePath; + final String _imagePath; final VoidCallback? _onCompleted; - static Future loadAssets() { + /// Returns a list of assets to be loaded for animations. + static List loadAssets() { Flame.images.prefix = ''; - return Flame.images.loadAll([ - Assets.images.bonusAnimation.dashNest.keyName, - Assets.images.bonusAnimation.sparkyTurboCharge.keyName, - Assets.images.bonusAnimation.dino.keyName, - Assets.images.bonusAnimation.android.keyName, - Assets.images.bonusAnimation.google.keyName, - ]); + return [ + Flame.images.load(Assets.images.bonusAnimation.dashNest.keyName), + Flame.images.load(Assets.images.bonusAnimation.sparkyTurboCharge.keyName), + Flame.images.load(Assets.images.bonusAnimation.dino.keyName), + Flame.images.load(Assets.images.bonusAnimation.android.keyName), + Flame.images.load(Assets.images.bonusAnimation.google.keyName), + ]; + } + + @override + State createState() => _BonusAnimationState(); +} + +class _BonusAnimationState extends State + with TickerProviderStateMixin { + late SpriteAnimationController controller; + late SpriteAnimation animation; + bool shouldRunBuildCallback = true; + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + // When the animation is overwritten by another animation, we need to stop + // the callback in the build method as it will break the new animation. + // Otherwise we need to set up a new callback when a new animation starts to + // show the score view at the end of the animation. + @override + void didUpdateWidget(BonusAnimation oldWidget) { + shouldRunBuildCallback = oldWidget._imagePath == widget._imagePath; + + Future.delayed( + Duration(seconds: animation.totalDuration().ceil()), + () { + widget._onCompleted?.call(); + }, + ); + + super.didUpdateWidget(oldWidget); } @override Widget build(BuildContext context) { final spriteSheet = SpriteSheet.fromColumnsAndRows( - image: Flame.images.fromCache(imagePath), + image: Flame.images.fromCache(widget._imagePath), columns: 8, rows: 9, ); - final animation = spriteSheet.createAnimation( + animation = spriteSheet.createAnimation( row: 0, stepTime: 1 / 24, to: spriteSheet.rows * spriteSheet.columns, @@ -91,15 +134,22 @@ class BonusAnimation extends StatelessWidget { Future.delayed( Duration(seconds: animation.totalDuration().ceil()), () { - _onCompleted?.call(); + if (shouldRunBuildCallback) { + widget._onCompleted?.call(); + } }, ); + controller = SpriteAnimationController( + animation: animation, + vsync: this, + )..forward(); + return SizedBox( width: double.infinity, height: double.infinity, child: SpriteAnimationWidget( - animation: animation, + controller: controller, ), ); } diff --git a/lib/game/view/widgets/game_hud.dart b/lib/game/view/widgets/game_hud.dart index 2873a50c..8d5e24b8 100644 --- a/lib/game/view/widgets/game_hud.dart +++ b/lib/game/view/widgets/game_hud.dart @@ -65,7 +65,7 @@ class _ScoreViewDecoration extends StatelessWidget { @override Widget build(BuildContext context) { return ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(8)), + borderRadius: const BorderRadius.all(Radius.circular(12)), child: DecoratedBox( decoration: BoxDecoration( image: DecorationImage( @@ -81,8 +81,6 @@ class _ScoreViewDecoration extends StatelessWidget { } } -// TODO(arturplaczek): Waiting for new version of SpriteAnimationWidget. -// https://github.com/flame-engine/flame/pull/1552. class _AnimationView extends StatelessWidget { const _AnimationView({ Key? key, diff --git a/lib/game/view/widgets/score_view.dart b/lib/game/view/widgets/score_view.dart index 52ac4692..288ea05c 100644 --- a/lib/game/view/widgets/score_view.dart +++ b/lib/game/view/widgets/score_view.dart @@ -1,5 +1,3 @@ -// ignore_for_file: public_member_api_docs - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:pinball/game/game.dart'; @@ -7,7 +5,11 @@ import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/theme/theme.dart'; import 'package:pinball_components/pinball_components.dart'; +/// {@template score_view} +/// [Widget] that displays the score. +/// {@endtemplate} class ScoreView extends StatelessWidget { + /// {@macro score_view} const ScoreView({Key? key}) : super(key: key); @override @@ -61,7 +63,7 @@ class _ScoreDisplay extends StatelessWidget { ), ), const _ScoreText(), - const BallCountDisplay(), + const RoundCountDisplay(), ], ); } diff --git a/lib/game/view/widgets/widgets.dart b/lib/game/view/widgets/widgets.dart index fb88df1a..5d1fccf8 100644 --- a/lib/game/view/widgets/widgets.dart +++ b/lib/game/view/widgets/widgets.dart @@ -1,5 +1,5 @@ -export 'ball_count_display.dart'; export 'bonus_animation.dart'; export 'game_hud.dart'; export 'play_button_overlay.dart'; +export 'round_count_display.dart'; export 'score_view.dart'; diff --git a/test/game/view/widgets/bonus_animation_test.dart b/test/game/view/widgets/bonus_animation_test.dart index a24003c2..cb938370 100644 --- a/test/game/view/widgets/bonus_animation_test.dart +++ b/test/game/view/widgets/bonus_animation_test.dart @@ -3,11 +3,11 @@ import 'dart:async'; import 'dart:ui' as ui; import 'package:flame/assets.dart'; -import 'package:flame/widgets.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pinball/game/view/widgets/bonus_animation.dart'; +import 'package:pinball_flame/pinball_flame.dart'; import '../../../helpers/helpers.dart'; @@ -19,7 +19,7 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); setUp(() async { - await BonusAnimation.loadAssets(); + await Future.wait(BonusAnimation.loadAssets()); }); group('loads SpriteAnimationWidget correctly for', () { @@ -32,7 +32,7 @@ void main() { expect(find.byType(SpriteAnimationWidget), findsOneWidget); }); - testWidgets('dino', (tester) async { + testWidgets('dinoChomp', (tester) async { await tester.pumpApp( BonusAnimation.dinoChomp(), ); @@ -50,7 +50,7 @@ void main() { expect(find.byType(SpriteAnimationWidget), findsOneWidget); }); - testWidgets('google', (tester) async { + testWidgets('googleWord', (tester) async { await tester.pumpApp( BonusAnimation.googleWord(), ); @@ -59,7 +59,7 @@ void main() { expect(find.byType(SpriteAnimationWidget), findsOneWidget); }); - testWidgets('android', (tester) async { + testWidgets('androidSpaceship', (tester) async { await tester.pumpApp( BonusAnimation.androidSpaceship(), ); diff --git a/test/game/view/widgets/game_hud_test.dart b/test/game/view/widgets/game_hud_test.dart index 1423ebfc..f8307b05 100644 --- a/test/game/view/widgets/game_hud_test.dart +++ b/test/game/view/widgets/game_hud_test.dart @@ -24,7 +24,7 @@ void main() { setUp(() async { gameBloc = MockGameBloc(); - await BonusAnimation.loadAssets(); + await Future.wait(BonusAnimation.loadAssets()); whenListen( gameBloc,