I see a lot of tutorials explaining how to do 2D Sprite Animation with sprite sheets, based on the user's input (i.e. Move Left, Move Right ) etc.. etc..
I have already incorporated an AnimationManager in my game to handle these types of animations.
What I would like to do however is to play animations that have a set start and end position with a given speed. I'm trying to think of how I'd like to do it and perhaps leverage some of the already written Animation code I have.
Things that I feel stumped about:
- Should I use a timer? How will I increment the Sprite's position based on the speed otherwise? It makes logical sense to perhaps put it in the Update() however then I would need to keep track of whether the sprite is animating and the desired final Position?
- Clearly the speed of the animation (FPS) should depend on the distance I'd like to travel so that the animation runs throughout the length of any distance?
- Who should handle the moving of the position and animation if it's dependant on a distance? My animationManager or the sprite himself?
I couldn't seem to find any demo/example code online, so any feedback or links I'd greatly appreciate!
I'll post my AnimationManager so far to give a fill of what I'm working with:
public class AnimationManager
{
#region Member Variables
public delegate void AnimationComplete();
public event AnimationComplete AnimationFinished;
private Dictionary<String, Animation> _animations = null;
private Animation _currentAnimation;
private int _frameIndex;
private float _elapsedTime;
private AnimatedSprite _sprite;
#endregion
#region Initializers
public AnimationManager(AnimatedSprite sprite)
{
_animations = new Dictionary<string, Animation>();
_frameIndex = 0;
_elapsedTime = 0f;
_currentAnimation = null;
_sprite = sprite;
}
#endregion
#region Public Methods
public void Update(GameTime gameTime)
{
if (_currentAnimation == null)
return;
_elapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (_elapsedTime > _currentAnimation.TimePerFrame)
{
_frameIndex++;
if (_frameIndex > _currentAnimation.NumberOfFrames - 1 && !_currentAnimation.IsLooping)
{
_frameIndex--;
OnAnimationComplete();
}
_frameIndex = _frameIndex % _currentAnimation.NumberOfFrames;
_elapsedTime -= _currentAnimation.TimePerFrame;
}
}
public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Draw(_currentAnimation.Texture, _sprite.Position, _currentAnimation.GetFrame(_frameIndex).toRectangle(), Color.White, _sprite.Rotation, _currentAnimation.Origin, _sprite.Scale, SpriteEffects.None, _sprite.Layer);
}
public void PlayAnimation(String key)
{
Animation anim = _animations[key];
PlayAnimation(anim);
}
public void AddAnimation(Animation anim, String key)
{
_animations[key] = anim;
}
public Animation GetAnimation(String key)
{
return _animations[key];
}
#endregion
#region Private/Protected Methods
protected virtual void PlayAnimation(Animation anim)
{
if (_currentAnimation == anim)
return;
_currentAnimation = anim;
_frameIndex = 0;
}
// Invoke the Changed event; called whenever list changes
protected virtual void OnAnimationComplete()
{
if (AnimationFinished != null)
AnimationFinished();
}
#endregion
}
public class Animation
{
#region Fields
protected String _name;
protected List<Frame> _frames;
protected Texture2D _spriteSheet;
protected float _framesPerSec;
protected bool _looping;
protected int _width;
protected int _height;
protected Vector2 _origin;
protected Animation _nextAnimation = null;
#endregion
#region Properties
public Animation NextAnimation
{
get { return _nextAnimation; }
set { _nextAnimation = value; }
}
public float TimePerFrame
{
get { return 1.0f / (float)_framesPerSec; }
}
public Vector2 Origin
{
set { _origin = value; }
get { return _origin; }
}
public Texture2D Texture
{
get { return _spriteSheet; }
}
public int Width
{
get { return _width; }
}
public int Height
{
get { return _height; }
}
public String Name
{
get { return _name; }
}
public float Speed
{
get { return _framesPerSec; }
set { _framesPerSec = value; }
}
public bool IsLooping
{
get { return _looping; }
}
public int NumberOfFrames
{
get { return _frames.Count ; }
}
#endregion
#region Initialization
public Animation(String name, Texture2D spriteSheet, bool looping, float speed, int width, int height)
{
_name = name;
_frames = new List<Frame>();
_spriteSheet = spriteSheet;
_framesPerSec = speed;
_looping = looping;
_width = width;
_height = height;
_origin = Vector2.Zero;
}
#endregion
public void AddFrame(Vector2 pos)
{
_frames.Add(new Frame(pos, _width, _height));
}
public Animation.Frame GetFrame(int frameIndex)
{
return _frames[frameIndex];
}
}