From a35d3a10abfe9e5caab1a646e0980d03fbf585d1 Mon Sep 17 00:00:00 2001 From: Adil Hanney Date: Mon, 7 Aug 2023 18:17:04 +0100 Subject: [PATCH] fix: Reset _completeCompleter in ticker (#2636) I was running this code: ```dart void attack() async { print('Attack started'); current = PlayerState.attack; final attackTicker = animationTicker!; await attackTicker.completed; print('Attack ticker completed'); attackTicker.reset(); current = PlayerState.idle; } ``` and `attackTicker.completed` would get stuck as permanently completed after the first completion. --- .../flame/lib/src/sprite_animation_ticker.dart | 15 +++++++++++---- .../test/sprite_animation_ticker_test.dart | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/flame/lib/src/sprite_animation_ticker.dart b/packages/flame/lib/src/sprite_animation_ticker.dart index ab9099f5994..a6f3c2754f3 100644 --- a/packages/flame/lib/src/sprite_animation_ticker.dart +++ b/packages/flame/lib/src/sprite_animation_ticker.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flame/components.dart'; +import 'package:meta/meta.dart'; /// A helper class to make the [spriteAnimation] tick. class SpriteAnimationTicker { @@ -30,7 +31,8 @@ class SpriteAnimationTicker { /// Registered method to be triggered when the animation complete. void Function()? onComplete; - Completer? _completeCompleter; + @visibleForTesting + Completer? completeCompleter; /// The current frame that should be displayed. SpriteAnimationFrame get currentFrame => spriteAnimation.frames[currentIndex]; @@ -54,9 +56,9 @@ class SpriteAnimationTicker { return Future.value(); } - _completeCompleter ??= Completer(); + completeCompleter ??= Completer(); - return _completeCompleter!.future; + return completeCompleter!.future; } /// Resets the animation, like it would just have been created. @@ -66,6 +68,11 @@ class SpriteAnimationTicker { currentIndex = 0; _done = false; _started = false; + + // Reset completeCompleter if it's already completed + if (completeCompleter?.isCompleted ?? false) { + completeCompleter = null; + } } /// Sets this animation to be on the last frame. @@ -127,7 +134,7 @@ class SpriteAnimationTicker { } else { _done = true; onComplete?.call(); - _completeCompleter?.complete(); + completeCompleter?.complete(); return; } } else { diff --git a/packages/flame/test/sprite_animation_ticker_test.dart b/packages/flame/test/sprite_animation_ticker_test.dart index 567de61ed2c..ab1c1fe8a12 100644 --- a/packages/flame/test/sprite_animation_ticker_test.dart +++ b/packages/flame/test/sprite_animation_ticker_test.dart @@ -145,5 +145,22 @@ void main() { expectLater(animationTicker.completed, doesNotComplete); }, ); + + test("completed doesn't complete after the animation is reset", () async { + final sprite = MockSprite(); + final animationTicker = SpriteAnimation.spriteList( + [sprite], + stepTime: 1, + loop: false, + ).createTicker(); + + animationTicker.completed; + animationTicker.update(1); + expect(animationTicker.completeCompleter!.isCompleted, true); + + animationTicker.reset(); + animationTicker.completed; + expect(animationTicker.completeCompleter!.isCompleted, false); + }); }); }