diff --git a/source/MonoGame.Extended/AnimationComponent.cs b/source/MonoGame.Extended/AnimationComponent.cs index 0573334cb..c56cae78a 100644 --- a/source/MonoGame.Extended/AnimationComponent.cs +++ b/source/MonoGame.Extended/AnimationComponent.cs @@ -8,10 +8,10 @@ public class AnimationComponent : GameComponent public AnimationComponent(Game game) : base(game) { - Animations = new List(); + Animations = new List(); } - public List Animations { get; } + public List Animations { get; } public override void Update(GameTime gameTime) { diff --git a/source/MonoGame.Extended/Animations/Animation.cs b/source/MonoGame.Extended/Animations/AnimationController.cs similarity index 92% rename from source/MonoGame.Extended/Animations/Animation.cs rename to source/MonoGame.Extended/Animations/AnimationController.cs index 5d6473912..ad4cdf9f4 100644 --- a/source/MonoGame.Extended/Animations/Animation.cs +++ b/source/MonoGame.Extended/Animations/AnimationController.cs @@ -8,12 +8,12 @@ namespace MonoGame.Extended.Animations; /// -/// Represents an animation with various control features such as play, pause, stop, looping, reversing, and -/// ping-pong effects. +/// Represents an animation controller with features to play, pause, stop, reset, and set the state of +/// animation playback such as looping, reversing, and ping-pong effects. /// -public class Animation : IAnimation +public class AnimationController : IAnimationController { - private readonly IAnimationDefinition _definition; + private readonly IAnimation _definition; private int _direction; /// @@ -44,7 +44,7 @@ public bool IsReversed public double Speed { get; set; } /// - public event Action OnAnimationEvent; + public event Action OnAnimationEvent; /// public TimeSpan CurrentFrameTimeRemaining { get; private set; } @@ -56,10 +56,10 @@ public bool IsReversed public int FrameCount => _definition.FrameCount; /// - /// Initializes a new instance of the class with the specified definition. + /// Initializes a new instance of the class with the specified definition. /// /// The definition of the animation. - public Animation(IAnimationDefinition definition) + public AnimationController(IAnimation definition) { _definition = definition; @@ -101,7 +101,7 @@ public bool Play(int startingFrame) { if (startingFrame < 0 || startingFrame >= _definition.FrameCount) { - throw new ArgumentOutOfRangeException(nameof(startingFrame), $"{nameof(startingFrame)} cannot be less than zero or greater than or equal to the total number of frames in this {nameof(Animation)}"); + throw new ArgumentOutOfRangeException(nameof(startingFrame), $"{nameof(startingFrame)} cannot be less than zero or greater than or equal to the total number of frames in this {nameof(AnimationController)}"); } // Cannot play something that is already playing @@ -134,7 +134,7 @@ public void SetFrame(int index) { if (index < 0 || index >= _definition.FrameCount) { - throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of frames in this {nameof(Animation)}"); + throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of frames in this {nameof(AnimationController)}"); } CurrentFrame = index; diff --git a/source/MonoGame.Extended/Animations/AnimationEvent.cs b/source/MonoGame.Extended/Animations/AnimationEvent.cs index 1c932ed83..4f0d685eb 100644 --- a/source/MonoGame.Extended/Animations/AnimationEvent.cs +++ b/source/MonoGame.Extended/Animations/AnimationEvent.cs @@ -12,14 +12,14 @@ namespace MonoGame.Extended.Animations; public class AnimationEvent : EventArgs { /// - /// Gets the animation associated with the event. + /// Gets the animation controller associated with the event. /// - public IAnimation Animation { get; } + public IAnimationController Animation { get; } /// /// Gets the trigger that caused the event. /// public AnimationEventTrigger Trigger { get; } - internal AnimationEvent(IAnimation animation, AnimationEventTrigger trigger) => (Animation, Trigger) = (animation, trigger); + internal AnimationEvent(IAnimationController animation, AnimationEventTrigger trigger) => (Animation, Trigger) = (animation, trigger); } diff --git a/source/MonoGame.Extended/Animations/IAnimation.cs b/source/MonoGame.Extended/Animations/IAnimation.cs index 0224914c2..96550d7de 100644 --- a/source/MonoGame.Extended/Animations/IAnimation.cs +++ b/source/MonoGame.Extended/Animations/IAnimation.cs @@ -3,60 +3,25 @@ // See LICENSE file in the project root for full license information. using System; -using Microsoft.Xna.Framework; +using MonoGame.Extended.Graphics; namespace MonoGame.Extended.Animations; /// -/// Defines the interface for an animation with various control features such as play, pause, stop, looping, reversing, and ping-pong effects. +/// Defines the interface for an animation, specifying properties of the animation such as frames, looping, reversing, +/// and ping-pong effects. /// -public interface IAnimation : IDisposable +public interface IAnimation { /// - /// Gets a value indicating whether the animation is paused. + /// Gets the name of the animation. /// - bool IsPaused { get; } + string Name { get; } /// - /// Gets a value indicating whether the animation is currently animating. + /// Gets the read-only collection of frames in the animation. /// - bool IsAnimating { get; } - - /// - /// Gets or sets a value indicating whether the animation should loop. - /// - bool IsLooping { get; set; } - - /// - /// Gets or sets a value indicating whether the animation is reversed. - /// - bool IsReversed { get; set; } - - /// - /// Gets or sets a value indicating whether the animation should ping-pong (reverse direction at the ends). - /// - bool IsPingPong { get; set; } - - /// - /// Gets or sets the speed of the animation. - /// - /// The speed cannot be less than zero. - double Speed { get; set; } - - /// - /// Gets or sets the action to perform when an animation event is triggered. - /// - event Action OnAnimationEvent; - - /// - /// Gets the time remaining for the current frame. - /// - TimeSpan CurrentFrameTimeRemaining { get; } - - /// - /// Gets the index of the current frame of the animation. - /// - int CurrentFrame { get; } + ReadOnlySpan Frames { get; } /// /// Gets the total number of frames in the animation. @@ -64,86 +29,17 @@ public interface IAnimation : IDisposable int FrameCount { get; } /// - /// Sets the animation to a specified frame. - /// - /// The index of the frame to set. - /// - /// Thrown when the parameter is less than zero or greater than or equal to the total - /// number of frames. - /// - void SetFrame(int index); - - /// - /// Plays the animation from the beginning. - /// - /// - /// if the animation was successfully started; otherwise, . - /// - bool Play(); - - /// - /// Plays the animation from a specified starting frame. - /// - /// The frame to start the animation from. - /// - /// if the animation was successfully started; otherwise, . - /// - /// - /// Thrown when the parameter is less than zero or greater than or equal to the - /// total number of frames. - /// - bool Play(int startingFrame); - - /// - /// Pauses the animation. - /// - /// - /// if the animation was successfully paused; otherwise, . - /// - bool Pause(); - - /// - /// Pauses the animation. - /// - /// If set to , resets the frame duration. - /// - /// if the animation was successfully paused; otherwise, . - /// - bool Pause(bool resetFrameDuration); - - /// - /// Unpauses the animation. - /// - /// - /// if the animation was successfully unpaused; otherwise, . - /// - bool Unpause(); - - /// - /// Unpauses the animation. - /// - /// If set to , advances to the next frame. - /// - /// if the animation was successfully unpaused; otherwise, . - /// - bool Unpause(bool advanceToNextFrame); - - /// - /// Updates the animation. + /// Gets a value indicating whether the animation should loop. /// - /// A snapshot of the timing values for the current update cycle. - void Update(GameTime gameTime); + bool IsLooping { get; } /// - /// Stops the animation. + /// Gets a value indicating whether the animation is reversed. /// - /// - /// if the animation was successfully stopped; otherwise, . - /// - bool Stop(); + bool IsReversed { get; } /// - /// Resets the animation to its initial state. + /// Gets a value indicating whether the animation should ping-pong (reverse direction at the ends). /// - void Reset(); + bool IsPingPong { get; } } diff --git a/source/MonoGame.Extended/Animations/IAnimationController.cs b/source/MonoGame.Extended/Animations/IAnimationController.cs new file mode 100644 index 000000000..5a5d205b7 --- /dev/null +++ b/source/MonoGame.Extended/Animations/IAnimationController.cs @@ -0,0 +1,155 @@ +// Copyright (c) Craftwork Games. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System; +using Microsoft.Xna.Framework; + +namespace MonoGame.Extended.Animations; + +/// +/// Defines the interface for an animation controller with features to play, pause, stop, reset, and set the state of +/// animation playback such as looping, reversing, and ping-pong effects. +/// +public interface IAnimationController : IDisposable +{ + /// + /// Gets a value indicating whether this animation controller has been disposed of. + /// + bool IsDisposed { get; } + + /// + /// Gets a value indicating whether the animation is paused. + /// + bool IsPaused { get; } + + /// + /// Gets a value indicating whether the animation is currently animating. + /// + bool IsAnimating { get; } + + /// + /// Gets or sets a value indicating whether the animation should loop. + /// + bool IsLooping { get; set; } + + /// + /// Gets or sets a value indicating whether the animation is reversed. + /// + bool IsReversed { get; set; } + + /// + /// Gets or sets a value indicating whether the animation should ping-pong (reverse direction at the ends). + /// + bool IsPingPong { get; set; } + + /// + /// Gets or sets the speed of the animation. + /// + /// The speed cannot be less than zero. + double Speed { get; set; } + + /// + /// Gets or sets the action to perform when an animation event is triggered. + /// + event Action OnAnimationEvent; + + /// + /// Gets the time remaining for the current frame. + /// + TimeSpan CurrentFrameTimeRemaining { get; } + + /// + /// Gets the index of the current frame of the animation. + /// + int CurrentFrame { get; } + + /// + /// Gets the total number of frames in the animation. + /// + int FrameCount { get; } + + /// + /// Sets the animation to a specified frame. + /// + /// The index of the frame to set. + /// + /// Thrown when the parameter is less than zero or greater than or equal to the total + /// number of frames. + /// + void SetFrame(int index); + + /// + /// Plays the animation from the beginning. + /// + /// + /// if the animation was successfully started; otherwise, . + /// + bool Play(); + + /// + /// Plays the animation from a specified starting frame. + /// + /// The frame to start the animation from. + /// + /// if the animation was successfully started; otherwise, . + /// + /// + /// Thrown when the parameter is less than zero or greater than or equal to the + /// total number of frames. + /// + bool Play(int startingFrame); + + /// + /// Pauses the animation. + /// + /// + /// if the animation was successfully paused; otherwise, . + /// + bool Pause(); + + /// + /// Pauses the animation. + /// + /// If set to , resets the frame duration. + /// + /// if the animation was successfully paused; otherwise, . + /// + bool Pause(bool resetFrameDuration); + + /// + /// Unpauses the animation. + /// + /// + /// if the animation was successfully unpaused; otherwise, . + /// + bool Unpause(); + + /// + /// Unpauses the animation. + /// + /// If set to , advances to the next frame. + /// + /// if the animation was successfully unpaused; otherwise, . + /// + bool Unpause(bool advanceToNextFrame); + + /// + /// Updates the animation. + /// + /// A snapshot of the timing values for the current update cycle. + void Update(GameTime gameTime); + + /// + /// Stops the animation. + /// + /// + /// if the animation was successfully stopped; otherwise, . + /// + bool Stop(); + + /// + /// Resets the animation to its initial state. + /// + void Reset(); +} diff --git a/source/MonoGame.Extended/Animations/IAnimationDefinition.cs b/source/MonoGame.Extended/Animations/IAnimationDefinition.cs deleted file mode 100644 index fa48ae5bb..000000000 --- a/source/MonoGame.Extended/Animations/IAnimationDefinition.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Craftwork Games. All rights reserved. -// Licensed under the MIT license. -// See LICENSE file in the project root for full license information. - -using System; - -namespace MonoGame.Extended.Animations; - -/// -/// Defines the interface for an animation definition, specifying properties of the animation such as frames, looping, -/// reversing, and ping-pong effects. -/// -public interface IAnimationDefinition -{ - /// - /// Gets the name of the animation. - /// - string Name { get; } - - /// - /// Gets the read-only collection of frames in the animation. - /// - ReadOnlySpan Frames { get; } - - /// - /// Gets the total number of frames in the animation. - /// - int FrameCount { get; } - - /// - /// Gets a value indicating whether the animation should loop. - /// - bool IsLooping { get; } - - /// - /// Gets a value indicating whether the animation is reversed. - /// - bool IsReversed { get; } - - /// - /// Gets a value indicating whether the animation should ping-pong (reverse direction at the ends). - /// - bool IsPingPong { get; } -} diff --git a/source/MonoGame.Extended/Graphics/AnimatedSprite.cs b/source/MonoGame.Extended/Graphics/AnimatedSprite.cs index 15096f1f5..2f22f11fa 100644 --- a/source/MonoGame.Extended/Graphics/AnimatedSprite.cs +++ b/source/MonoGame.Extended/Graphics/AnimatedSprite.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. // See LICENSE file in the project root for full license information. +using System; +using System.Collections.Generic; using Microsoft.Xna.Framework; using MonoGame.Extended.Animations; @@ -12,30 +14,66 @@ namespace MonoGame.Extended.Graphics; /// public class AnimatedSprite : Sprite { + private readonly SpriteSheet _spriteSheet; + private IAnimation _animation; + private readonly Texture2DRegion[] _regions; /// - /// Gets the animation used by this animated sprite. + /// Gets the animation controller used to control the current animation of this animated sprite. /// - public IAnimation Animation { get; } + public IAnimationController Controller { get; private set; } - internal AnimatedSprite(SpriteSheetAnimationDefinition definition, Texture2DRegion[] regions) - : base(regions[0]) + /// + /// Initializes a new instance of the class with the specified + /// . + /// + /// The that contains the animations. + public AnimatedSprite(SpriteSheet spriteSheet) + : base(spriteSheet.TextureAtlas[0]) + { + ArgumentNullException.ThrowIfNull(spriteSheet); + _spriteSheet = spriteSheet; + } + + /// + /// Initializes a new instance of the class with the specified + /// . + /// + /// The that contains the animations. + /// The initial animation to play + public AnimatedSprite(SpriteSheet spriteSheet, string initialAnimation) :this(spriteSheet) + { + SpriteSheetAnimation definition = spriteSheet.GetAnimation(initialAnimation); + Controller = new AnimationController(definition); + } + + /// + /// Sets the animation to use for this animated sprite. + /// + /// The name of the animation. + /// The of the animation. + /// + /// Thrown if the source spritesheet does not contain an animation a name that matches the parameter. + /// + public IAnimationController SetAnimation(string name) { - Animation = new Animation(definition); - _regions = regions; + _animation = _spriteSheet.GetAnimation(name); + Controller = new AnimationController(_animation); + return Controller; } /// public void Update(GameTime gameTime) { - int index = Animation.CurrentFrame; - Animation.Update(gameTime); + int index = Controller.CurrentFrame; + Controller.Update(gameTime); // If the current frame changed during the update, change the texture region - if (index != Animation.CurrentFrame) + if (index != Controller.CurrentFrame) { - TextureRegion = _regions[Animation.CurrentFrame]; + int regionIndex = _animation.Frames[Controller.CurrentFrame].FrameIndex; + TextureRegion = _spriteSheet.TextureAtlas[regionIndex]; } } } diff --git a/source/MonoGame.Extended/Graphics/SpriteSheet.cs b/source/MonoGame.Extended/Graphics/SpriteSheet.cs index 1d65a2921..b95eb8d76 100644 --- a/source/MonoGame.Extended/Graphics/SpriteSheet.cs +++ b/source/MonoGame.Extended/Graphics/SpriteSheet.cs @@ -12,7 +12,7 @@ namespace MonoGame.Extended.Graphics; /// public class SpriteSheet { - private readonly Dictionary _animations = new Dictionary(); + private readonly Dictionary _animations = new Dictionary(); /// /// Gets the number of animations defined in the sprite sheet. @@ -57,31 +57,22 @@ public SpriteSheet(string name, Texture2DAtlas textureAtlas) /// A new instance. public Sprite CreateSprite(string regionName) => TextureAtlas.CreateSprite(regionName); - /// - /// Creates an animated sprite from the specified animation name. - /// - /// The name of the animation. - /// A new instance. - public AnimatedSprite CreateAnimatedSprite(string animationName) - { - SpriteSheetAnimationDefinition animationDefinition = _animations[animationName]; - Texture2DRegion[] regions = TextureAtlas.GetRegions(animationDefinition.Frames); - return new AnimatedSprite(animationDefinition, regions); - } /// /// Defines a new animation for the sprite sheet. /// /// The name of the animation. /// The action to build the animation definition. - public void DefineAnimation(string name, Action buildAction) + public void DefineAnimation(string name, Action buildAction) { - SpriteSheetAnimationDefinitionBuilder builder = new SpriteSheetAnimationDefinitionBuilder(name, this); + SpriteSheetAnimationBuilder builder = new SpriteSheetAnimationBuilder(name, this); buildAction(builder); - SpriteSheetAnimationDefinition definition = builder.Build(); + SpriteSheetAnimation definition = builder.Build(); _animations.Add(name, definition); } + public SpriteSheetAnimation GetAnimation(string name) => _animations[name]; + /// /// Removes the animation definition with the specified name. /// diff --git a/source/MonoGame.Extended/Graphics/SpriteSheetAnimationDefinition.cs b/source/MonoGame.Extended/Graphics/SpriteSheetAnimation.cs similarity index 77% rename from source/MonoGame.Extended/Graphics/SpriteSheetAnimationDefinition.cs rename to source/MonoGame.Extended/Graphics/SpriteSheetAnimation.cs index 2375401b1..db6c12944 100644 --- a/source/MonoGame.Extended/Graphics/SpriteSheetAnimationDefinition.cs +++ b/source/MonoGame.Extended/Graphics/SpriteSheetAnimation.cs @@ -7,7 +7,7 @@ namespace MonoGame.Extended.Graphics; -internal class SpriteSheetAnimationDefinition : IAnimationDefinition +public class SpriteSheetAnimation : IAnimation { private readonly SpriteSheetAnimationFrame[] _frames; @@ -18,7 +18,7 @@ internal class SpriteSheetAnimationDefinition : IAnimationDefinition public bool IsReversed { get; } public bool IsPingPong { get; } - internal SpriteSheetAnimationDefinition(string name, SpriteSheetAnimationFrame[] frames, bool isLooping, bool isReversed, bool isPingPong) + internal SpriteSheetAnimation(string name, SpriteSheetAnimationFrame[] frames, bool isLooping, bool isReversed, bool isPingPong) { Name = name; IsLooping = isLooping; diff --git a/source/MonoGame.Extended/Graphics/SpriteSheetAnimationDefinitionBuilder.cs b/source/MonoGame.Extended/Graphics/SpriteSheetAnimationBuilder.cs similarity index 64% rename from source/MonoGame.Extended/Graphics/SpriteSheetAnimationDefinitionBuilder.cs rename to source/MonoGame.Extended/Graphics/SpriteSheetAnimationBuilder.cs index 53ce12737..52f40fe50 100644 --- a/source/MonoGame.Extended/Graphics/SpriteSheetAnimationDefinitionBuilder.cs +++ b/source/MonoGame.Extended/Graphics/SpriteSheetAnimationBuilder.cs @@ -8,9 +8,9 @@ namespace MonoGame.Extended.Graphics; /// -/// A builder class for creating instances. +/// A builder class for creating instances. /// -public sealed class SpriteSheetAnimationDefinitionBuilder +public sealed class SpriteSheetAnimationBuilder { private readonly string _name; private readonly SpriteSheet _spriteSheet; @@ -19,7 +19,7 @@ public sealed class SpriteSheetAnimationDefinitionBuilder private bool _isReversed; private bool _isPingPong; - internal SpriteSheetAnimationDefinitionBuilder(string name, SpriteSheet spriteSheet) + internal SpriteSheetAnimationBuilder(string name, SpriteSheet spriteSheet) { _name = name; _spriteSheet = spriteSheet; @@ -30,8 +30,8 @@ internal SpriteSheetAnimationDefinitionBuilder(string name, SpriteSheet spriteSh /// /// The index of the region in the sprite sheet. /// The duration of the frame. - /// The instance for chaining. - public SpriteSheetAnimationDefinitionBuilder AddFrame(int regionIndex, TimeSpan duration) + /// The instance for chaining. + public SpriteSheetAnimationBuilder AddFrame(int regionIndex, TimeSpan duration) { SpriteSheetAnimationFrame frame = new SpriteSheetAnimationFrame(regionIndex, duration); _frames.Add(frame); @@ -43,8 +43,8 @@ public SpriteSheetAnimationDefinitionBuilder AddFrame(int regionIndex, TimeSpan /// /// The name of the region in the sprite sheet. /// The duration of the frame. - /// The instance for chaining. - public SpriteSheetAnimationDefinitionBuilder AddFrame(string regionName, TimeSpan duration) + /// The instance for chaining. + public SpriteSheetAnimationBuilder AddFrame(string regionName, TimeSpan duration) { int index = _spriteSheet.TextureAtlas.GetIndexOfRegion(regionName); return AddFrame(index, duration); @@ -54,8 +54,8 @@ public SpriteSheetAnimationDefinitionBuilder AddFrame(string regionName, TimeSpa /// Sets whether the animation should loop. /// /// If set to true, the animation will loop. - /// The instance for chaining. - public SpriteSheetAnimationDefinitionBuilder IsLooping(bool isLooping) + /// The instance for chaining. + public SpriteSheetAnimationBuilder IsLooping(bool isLooping) { _isLooping = isLooping; return this; @@ -65,8 +65,8 @@ public SpriteSheetAnimationDefinitionBuilder IsLooping(bool isLooping) /// Sets whether the animation should be reversed. /// /// If set to true, the animation will play in reverse. - /// The instance for chaining. - public SpriteSheetAnimationDefinitionBuilder IsReversed(bool isReversed) + /// The instance for chaining. + public SpriteSheetAnimationBuilder IsReversed(bool isReversed) { _isReversed = isReversed; return this; @@ -76,13 +76,13 @@ public SpriteSheetAnimationDefinitionBuilder IsReversed(bool isReversed) /// Sets whether the animation should ping-pong (reverse direction at the ends). /// /// If set to true, the animation will ping-pong. - /// The instance for chaining. - public SpriteSheetAnimationDefinitionBuilder IsPingPong(bool isPingPong) + /// The instance for chaining. + public SpriteSheetAnimationBuilder IsPingPong(bool isPingPong) { _isPingPong = isPingPong; return this; } - internal SpriteSheetAnimationDefinition Build() => - new SpriteSheetAnimationDefinition(_name, _frames.ToArray(), _isLooping, _isReversed, _isPingPong); + internal SpriteSheetAnimation Build() => + new SpriteSheetAnimation(_name, _frames.ToArray(), _isLooping, _isReversed, _isPingPong); } diff --git a/source/MonoGame.Extended/Math/SizeF.cs b/source/MonoGame.Extended/Math/SizeF.cs index b4e890534..91f9f8392 100644 --- a/source/MonoGame.Extended/Math/SizeF.cs +++ b/source/MonoGame.Extended/Math/SizeF.cs @@ -169,6 +169,11 @@ public static SizeF Add(SizeF first, SizeF second) return Subtract(first, second); } + public static Vector2 operator -(Vector2 first, SizeF second) + { + return Subtract(first, second); + } + public static SizeF operator /(SizeF size, float value) { return new SizeF(size.Width / value, size.Height / value); diff --git a/tests/MonoGame.Extended.Tests/Animations/AnimationTests.cs b/tests/MonoGame.Extended.Tests/Animations/AnimationTests.cs index 8dfcb9054..4c5ba801a 100644 --- a/tests/MonoGame.Extended.Tests/Animations/AnimationTests.cs +++ b/tests/MonoGame.Extended.Tests/Animations/AnimationTests.cs @@ -18,7 +18,7 @@ private class TestAnimationFrame : IAnimationFrame public TimeSpan Duration { get; set; } } - private class TestAnimationDefinition : IAnimationDefinition + private class TestAnimation : IAnimation { private readonly IAnimationFrame[] _frames; public string Name { get; set; } @@ -28,11 +28,11 @@ private class TestAnimationDefinition : IAnimationDefinition public bool IsReversed { get; set; } public bool IsPingPong { get; set; } - public TestAnimationDefinition(IAnimationFrame[] frames) => _frames = frames; + public TestAnimation(IAnimationFrame[] frames) => _frames = frames; } - private readonly IAnimationDefinition _definition; - private readonly Animation _animation; + private readonly IAnimation _animation; + private readonly IAnimationController _animationController; public AnimationTests() { @@ -41,94 +41,95 @@ public AnimationTests() new TestAnimationFrame { FrameIndex = 0, Duration = TimeSpan.FromSeconds(1) }, new TestAnimationFrame { FrameIndex = 1, Duration = TimeSpan.FromSeconds(1) } }; - _definition = new TestAnimationDefinition(frames) + _animation = new TestAnimation(frames) { FrameCount = frames.Length, IsLooping = false, IsReversed = false, IsPingPong = false }; - _animation = new Animation(_definition); + + _animationController = new AnimationController(_animation); } [Fact] public void Play_ShouldStartAnimation() { - var result = _animation.Play(); + var result = _animationController.Play(); Assert.True(result); - Assert.True(_animation.IsAnimating); - Assert.Equal(0, _animation.CurrentFrame); + Assert.True(_animationController.IsAnimating); + Assert.Equal(0, _animationController.CurrentFrame); } [Fact] public void Play_ShouldThrowException_ForInvalidFrame() { - Assert.Throws(() => _animation.Play(-1)); - Assert.Throws(() => _animation.Play(10)); + Assert.Throws(() => _animationController.Play(-1)); + Assert.Throws(() => _animationController.Play(10)); } [Fact] public void Pause_ShouldPauseAnimation() { - _animation.Play(); - var result = _animation.Pause(); + _animationController.Play(); + var result = _animationController.Pause(); Assert.True(result); - Assert.True(_animation.IsPaused); + Assert.True(_animationController.IsPaused); } [Fact] public void Pause_ShouldResetFrameDuration_WhenSpecified() { - _animation.Play(); - _animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(0.5))); + _animationController.Play(); + _animationController.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(0.5))); - var result = _animation.Pause(true); + var result = _animationController.Pause(true); Assert.True(result); - Assert.Equal(_definition.Frames[0].Duration, _animation.CurrentFrameTimeRemaining); + Assert.Equal(_animation.Frames[0].Duration, _animationController.CurrentFrameTimeRemaining); } [Fact] public void UnPause_ShouldResumeAnimation() { - _animation.Play(); - _animation.Pause(); - var result = _animation.Unpause(); + _animationController.Play(); + _animationController.Pause(); + var result = _animationController.Unpause(); Assert.True(result); - Assert.False(_animation.IsPaused); + Assert.False(_animationController.IsPaused); } [Fact] public void UnPause_ShouldAdvanceFrame_WhenSpecified() { - _animation.Play(); - _animation.Pause(); - var result = _animation.Unpause(true); + _animationController.Play(); + _animationController.Pause(); + var result = _animationController.Unpause(true); Assert.True(result); - Assert.Equal(1, _animation.CurrentFrame); + Assert.Equal(1, _animationController.CurrentFrame); } [Fact] public void Stop_ShouldStopAnimation() { - _animation.Play(); - var result = _animation.Stop(); + _animationController.Play(); + var result = _animationController.Stop(); Assert.True(result); - Assert.False(_animation.IsAnimating); + Assert.False(_animationController.IsAnimating); } [Fact] public void Update_ShouldAdvanceFrame() { - _animation.Play(); - _animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1))); + _animationController.Play(); + _animationController.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1))); - Assert.Equal(1, _animation.CurrentFrame); + Assert.Equal(1, _animationController.CurrentFrame); } [Fact] @@ -139,7 +140,7 @@ public void Update_ShouldTriggerAnimationEvents() bool animationLoopTriggered = false; bool animationCompletedTriggered = false; - _animation.OnAnimationEvent += (anim, trigger) => + _animationController.OnAnimationEvent += (anim, trigger) => { switch (trigger) { @@ -158,63 +159,63 @@ public void Update_ShouldTriggerAnimationEvents() } }; - _animation.Play(); - _animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1))); + _animationController.Play(); + _animationController.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1))); Assert.True(frameBeginTriggered); Assert.True(frameEndTriggered); - _animation.IsLooping = true; - _animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1))); + _animationController.IsLooping = true; + _animationController.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1))); Assert.True(animationLoopTriggered); - _animation.IsLooping = false; - _animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(2))); + _animationController.IsLooping = false; + _animationController.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(2))); Assert.True(animationCompletedTriggered); } [Fact] public void Update_ShouldLoopAnimation() { - _animation.IsLooping = true; - _animation.Play(); - _animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(2.1))); + _animationController.IsLooping = true; + _animationController.Play(); + _animationController.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(2.1))); - Assert.Equal(0, _animation.CurrentFrame); + Assert.Equal(0, _animationController.CurrentFrame); } [Fact] public void Reset_ShouldResetAnimation() { - _animation.Play(); - _animation.Reset(); + _animationController.Play(); + _animationController.Reset(); - Assert.False(_animation.IsAnimating); - Assert.True(_animation.IsPaused); - Assert.Equal(0, _animation.CurrentFrame); + Assert.False(_animationController.IsAnimating); + Assert.True(_animationController.IsPaused); + Assert.Equal(0, _animationController.CurrentFrame); } [Fact] public void SetFrame_ShouldChangeCurrentFrame() { - _animation.SetFrame(1); + _animationController.SetFrame(1); - Assert.Equal(1, _animation.CurrentFrame); - Assert.Equal(_definition.Frames[1].Duration, _animation.CurrentFrameTimeRemaining); + Assert.Equal(1, _animationController.CurrentFrame); + Assert.Equal(_animation.Frames[1].Duration, _animationController.CurrentFrameTimeRemaining); } [Fact] public void SetFrame_ShouldThrowException_ForInvalidFrame() { - Assert.Throws(() => _animation.SetFrame(-1)); - Assert.Throws(() => _animation.SetFrame(10)); + Assert.Throws(() => _animationController.SetFrame(-1)); + Assert.Throws(() => _animationController.SetFrame(10)); } [Fact] public void Dispose_ShouldDisposeAnimation() { - _animation.Dispose(); + _animationController.Dispose(); - Assert.True(_animation.IsDisposed); + Assert.True(_animationController.IsDisposed); } }