Skip to content

Commit

Permalink
fix: SpriteAnimationWidget can now be update animation safely (#1738)
Browse files Browse the repository at this point in the history
* Replace SingleTickerProviderStateMixin to TickerProviderStateMixin

* Adding failing test

* Re-use the animation controller

* Add some tests

* Remove redundant removing listener

Co-authored-by: Erick <erickzanardoo@gmail.com>
  • Loading branch information
Hwan-seok and erickzanardo authored Jun 29, 2022
1 parent 9f35b15 commit eb07019
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 9 deletions.
18 changes: 9 additions & 9 deletions packages/flame/lib/src/widgets/animation_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ class _InternalSpriteAnimationWidgetState
@override
void initState() {
super.initState();
widget.animation.onComplete = _pauseAnimation;
_setupController();
if (widget.playing) {
_initAnimation();
Expand Down Expand Up @@ -140,17 +139,18 @@ class _InternalSpriteAnimationWidgetState
}

void _setupController() {
_controller?.dispose();
widget.animation.onComplete = _pauseAnimation;
_controller ??= AnimationController(vsync: this)
..addListener(_onAnimationValueChanged);
}

_controller = AnimationController(vsync: this)
..addListener(() {
final now = DateTime.now().millisecond.toDouble();
void _onAnimationValueChanged() {
final now = DateTime.now().millisecond.toDouble();

final dt = max(0, (now - (_lastUpdated ?? 0)) / 1000).toDouble();
widget.animation.update(dt);
final dt = max(0, (now - (_lastUpdated ?? 0)) / 1000).toDouble();
widget.animation.update(dt);

setState(() => _lastUpdated = now);
});
setState(() => _lastUpdated = now);
}

void _pauseAnimation() {
Expand Down
26 changes: 26 additions & 0 deletions packages/flame/test/widgets/sprite_animation_widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,31 @@ Future<void> main() async {
expect(spriteAnimationWidgetFinder, findsOneWidget);
},
);

testWidgets('can safely change animation parameter', (tester) async {
final frames = List.generate(5, (_) => Sprite(image));
final animation1 = SpriteAnimation.spriteList(frames, stepTime: 0.1);
final animation2 = SpriteAnimation.spriteList(frames, stepTime: 0.1);

await tester.pumpWidget(SpriteAnimationWidget(animation: animation1));
expect(animation1.onComplete, isNotNull);
expect(animation2.onComplete, isNull);

await tester.pump();
expect(animation1.elapsed, isNonZero);
expect(animation2.elapsed, isZero);

// This will call didUpdateWidget life cycle
await tester.pumpWidget(SpriteAnimationWidget(animation: animation2));
expect(animation1.onComplete, isNull);
expect(animation2.onComplete, isNotNull);

// Reset the replaced animation for clarifying the expectation
animation1.reset();

await tester.pump();
expect(animation1.elapsed, isZero);
expect(animation2.elapsed, isNonZero);
});
});
}

0 comments on commit eb07019

Please sign in to comment.