diff --git a/packages/flame/lib/src/components/sprite_animation_group_component.dart b/packages/flame/lib/src/components/sprite_animation_group_component.dart index dee4c7aebfd..b529ab4a89b 100644 --- a/packages/flame/lib/src/components/sprite_animation_group_component.dart +++ b/packages/flame/lib/src/components/sprite_animation_group_component.dart @@ -29,6 +29,10 @@ class SpriteAnimationGroupComponent extends PositionComponent /// size of current animation sprite. bool _autoResize; + /// Whether the current animation's ticker should reset to the beginning + /// when it becomes current. + bool autoResetTicker; + /// Creates a component with an empty animation which can be set later SpriteAnimationGroupComponent({ Map? animations, @@ -36,6 +40,7 @@ class SpriteAnimationGroupComponent extends PositionComponent bool? autoResize, this.playing = true, this.removeOnFinish = const {}, + this.autoResetTicker = false, Paint? paint, super.position, super.size, @@ -83,6 +88,7 @@ class SpriteAnimationGroupComponent extends PositionComponent bool? autoResize, bool playing = true, Map removeOnFinish = const {}, + bool autoResetTicker = false, Paint? paint, Vector2? position, Vector2? size, @@ -104,6 +110,7 @@ class SpriteAnimationGroupComponent extends PositionComponent current: current, autoResize: autoResize, removeOnFinish: removeOnFinish, + autoResetTicker: autoResetTicker, playing: playing, paint: paint, position: position, @@ -125,8 +132,13 @@ class SpriteAnimationGroupComponent extends PositionComponent /// /// Will update [size] if [autoResize] is true. set current(T? value) { + final changed = value != current; _current = value; _resizeToSprite(); + + if (changed && autoResetTicker) { + animationTicker?.reset(); + } } /// Returns the map of animation state and their corresponding animations. diff --git a/packages/flame/test/components/sprite_animation_group_component_test.dart b/packages/flame/test/components/sprite_animation_group_component_test.dart index b025f6a2823..e01c83ac54c 100644 --- a/packages/flame/test/components/sprite_animation_group_component_test.dart +++ b/packages/flame/test/components/sprite_animation_group_component_test.dart @@ -353,4 +353,64 @@ Future main() async { expect(sizeChangeCounter, equals(4)); }); }); + + group('SpriteAnimationGroupComponent.autoResetTicker', () { + final sprite1 = Sprite(image, srcSize: Vector2.all(76)); + final sprite2 = Sprite(image, srcSize: Vector2.all(15)); + final animation1 = SpriteAnimation.spriteList( + List.filled(5, sprite1), + stepTime: 0.1, + loop: false, + ); + final animation2 = SpriteAnimation.spriteList( + List.filled(5, sprite2), + stepTime: 0.1, + loop: false, + ); + + test('does not reset ticker by default', () { + final component = SpriteAnimationGroupComponent<_AnimationState>( + animations: { + _AnimationState.idle: animation1, + _AnimationState.running: animation2, + }, + current: _AnimationState.idle, + ); + component.update(0.9); + expect(component.animationTicker!.currentIndex, 4); + + component.current = _AnimationState.running; + component.update(0.1); + expect(component.animationTicker!.currentIndex, 1); + + component.current = _AnimationState.idle; + expect(component.animationTicker!.currentIndex, 4); + + component.current = _AnimationState.running; + expect(component.animationTicker!.currentIndex, 1); + }); + + test('resets the ticker when enaled', () { + final component = SpriteAnimationGroupComponent<_AnimationState>( + animations: { + _AnimationState.idle: animation1, + _AnimationState.running: animation2, + }, + autoResetTicker: true, + current: _AnimationState.idle, + ); + component.update(0.9); + expect(component.animationTicker!.currentIndex, 4); + + component.current = _AnimationState.running; + component.update(0.1); + expect(component.animationTicker!.currentIndex, 1); + + component.current = _AnimationState.idle; + expect(component.animationTicker!.currentIndex, 0); + + component.current = _AnimationState.running; + expect(component.animationTicker!.currentIndex, 0); + }); + }); }