using System;
using System.Collections.Generic;
namespace Otter {
///
/// Graphic that is used for an animated sprite sheet.
///
///
public class Spritemap : Image {
#region Public Fields
///
/// The playback speed of all animations.
///
public float Speed = 1f;
#endregion
#region Public Properties
///
/// The total number of frames on the sprite sheet.
///
public int Frames { get; private set; }
///
/// The total number of columns on the sprite sheet.
///
public int Columns { get; private set; }
///
/// The total number of rows on the spirte sheet.
///
public int Rows { get; private set; }
///
/// The current buffered animation.
///
public TAnimType BufferedAnimation { get; private set; }
///
/// Determines if the sprite is playing animations.
///
public bool Active { get; private set; }
///
/// Determines if the sprite is advancing its current animation.
///
public bool Paused { get; private set; }
///
/// The dictionary of stored animations.
///
public Dictionary Anims { get; private set; }
///
/// The animation currently playing.
///
public TAnimType CurrentAnim { get; private set; }
///
/// The current frame of the animation on the sprite sheet.
///
public int CurrentFrame {
get {
return Anims[CurrentAnim].CurrentFrame;
}
set {
SetFrame(value);
}
}
///
/// The current frame index of the animation, from 0 to frame count - 1.
///
public int CurrentFrameIndex {
get {
return Anims[CurrentAnim].CurrentFrameIndex;
}
set {
Anims[CurrentAnim].CurrentFrameIndex = value;
}
}
#endregion
#region Constructors
///
/// Create a new Spritemap from a file path.
///
/// The file path to a texture to use for the sprite sheet.
/// The width of the animation.
/// The height of the animation.
public Spritemap(string source, int width, int height) : base(source) {
Initialize(width, height);
}
///
/// Create a new Spritemap from a Texture.
///
/// The Texture to use for the sprite sheet.
/// The width of a cell on the sprite sheet.
/// The height of a cell on the sprite sheet.
public Spritemap(Texture texture, int width, int height) : base(texture) {
Initialize(width, height);
}
///
/// Create a new Spritemap from an AtlasTexture.
///
/// The AtlasTexture to use for the sprite sheet.
/// The width of a cell on the sprite sheet.
/// The height of a cell on the sprite sheet.
public Spritemap(AtlasTexture texture, int width, int height) : base(texture) {
Initialize(width, height);
}
#endregion
#region Private Methods
protected void Initialize(int width, int height) {
Anims = new Dictionary();
// Try batching later.
//Batchable = true;
Width = width;
Height = height;
ClippingRegion = new Rectangle(0, 0, Width, Height);
Columns = (int)Math.Ceiling((float)TextureRegion.Width / Width);
Rows = (int)Math.Ceiling((float)TextureRegion.Height / Height);
Frames = Columns * Rows;
UpdateTextureRegion(0);
}
protected override void TextureChanged() {
// Dont do the same stuff as image :I
}
#endregion
#region Indexers
public Anim this[TAnimType anim] {
get { return Anim(anim); }
}
#endregion
#region Public Methods
///
/// Add an animation to the list of Anims.
///
/// The key to reference this animation.
/// The anim value.
public void Add(TAnimType a, Anim anim) {
Anims.Add(a, anim);
CurrentAnim = a;
}
///
/// Adds an animation using a string for frames and a single value for frame delay.
///
/// The key to store the animation with.
/// The frames of the animation from the sprite sheet. Example: "0,3,7-11,2,5"
/// The delay between advancing to the next frame.
/// The added animation.
public Anim Add(TAnimType a, string frames, float framedelays) {
var anim = new Anim(frames, framedelays.ToString());
Add(a, anim);
return anim;
}
///
/// Add an animation using a string for frames and a string for framedelays.
///
/// The key to store the animation with.
/// The frames of the animation from the sprite sheet. Example: "0,3,7-11,2,5"
/// The duration of time to show each frame. Example: "10,10,5,5,50"
/// The added animation.
public Anim Add(TAnimType a, string frames, string framedelays) {
var anim = new Anim(frames, framedelays);
Add(a, anim);
return anim;
}
///
/// Add an animation to the sprite.
///
/// The name of the animation.
/// An array of the frames to display.
/// An array of durations for each frame.
/// The added animation.
public Anim Add(TAnimType a, int[] frames, float[] frameDelay = null) {
var anim = new Anim(frames, frameDelay);
Add(a, anim);
return anim;
}
///
/// Adds an animation using an array for frames and a single value for frame delay.
///
/// The key to store the animation with.
/// The frames of the animation from the sprite sheet. Example: "0,3,7-11,2,5"
/// The delay between advancing to the next frame.
/// The added animation.
public Anim Add(TAnimType a, int[] frames, float framedelays) {
var anim = new Anim(frames, new float[] { framedelays });
Add(a, anim);
return anim;
}
///
/// Updates the animation. The sprite will not animate without this.
///
public override void Update() {
base.Update();
if (!Active) return;
if (!Anims.ContainsKey(CurrentAnim)) return;
if (Paused) return;
Anims[CurrentAnim].Update(Speed);
UpdateSprite();
}
void UpdateSprite() {
UpdateTextureRegion((int)Util.Clamp(Anims[CurrentAnim].CurrentFrame, 0, Frames));
}
///
/// Updates the internal source for the texture.
///
/// The frame in terms of the sprite sheet.
void UpdateTextureRegion(int frame) {
var top = (int)(Math.Floor((float)frame / Columns) * Height);
var left = (int)((frame % Columns) * Width);
if (TextureRegion != new Rectangle(left, top, Width, Height)) {
NeedsUpdate = true;
}
TextureRegion = new Rectangle(left, top, Width, Height);
}
///
/// Play the desired animation.
///
/// The animation to play.
/// Resets the animation back to the start before playing even if this is the same animation that was already playing.
public void Play(TAnimType a, bool forceReset = true) {
Active = true;
var pastAnim = CurrentAnim;
CurrentAnim = a;
if (Anims[CurrentAnim] != Anims[pastAnim] || forceReset) {
Anims[CurrentAnim].Reset();
}
Anims[CurrentAnim].Active = true;
UpdateSprite();
}
///
/// Buffers an animation but does not play it. Call Play() with no arguments to play the buffered animation.
///
/// The animation to buffer.
public void Buffer(TAnimType a) {
BufferedAnimation = a;
}
///
/// Plays an animation. If no animation is specified, play the buffered animation.
///
public void Play(bool forceReset = true) {
if (BufferedAnimation != null) {
Play(BufferedAnimation, forceReset);
}
else {
Play(CurrentAnim, forceReset);
}
UpdateSprite();
}
///
/// Get the animation with a specific key.
///
/// The key to search with.
/// The animation found.
public Anim Anim(TAnimType a) {
if (!Anims.ContainsKey(a)) return null;
return Anims[a];
}
///
/// Pause the playback of the animation.
///
public void Pause() {
Paused = true;
}
///
/// Resume the animation from the current position.
///
public void Resume() {
Paused = false;
}
///
/// Stop playback. This will reset the animation to the first frame.
///
public void Stop() {
Active = false;
Anims[CurrentAnim].Stop();
}
///
/// Set the current animation to a specific frame.
///
/// The frame in terms of the animation.
public void SetFrame(int frame) {
if (!Active) return;
Anims[CurrentAnim].CurrentFrameIndex = frame;
Anims[CurrentAnim].Reset();
}
///
/// Set the current animation to a specific frame and pause.
///
/// The frame in terms of the animation.
public void FreezeFrame(int frame) {
if (!Active) return;
Paused = true;
Anims[CurrentAnim].CurrentFrameIndex = frame;
UpdateTextureRegion(Anims[CurrentAnim].CurrentFrame);
}
///
/// Set the sprite to a frame on the sprite sheet itself.
/// This will disable the current animation!
///
/// The global frame in terms of the sprite sheet.
public void SetGlobalFrame(int frame) {
Active = false;
UpdateTextureRegion(frame);
}
///
/// Resets the current animation back to the first frame.
///
public void Reset() {
Anims[CurrentAnim].Reset();
}
///
/// Clear the list of animations.
///
public void Clear() {
Anims.Clear();
}
#endregion
}
public class Spritemap : Spritemap {
///
/// Create a new Spritemap from a file path.
///
/// The file path to a texture to use for the sprite sheet.
/// The width of the animation.
/// The height of the animation.
public Spritemap(string source, int width, int height) : base(source, width, height) {
Initialize(width, height);
}
///
/// Create a new Spritemap from a Texture.
///
/// The Texture to use for the sprite sheet.
/// The width of a cell on the sprite sheet.
/// The height of a cell on the sprite sheet.
public Spritemap(Texture texture, int width, int height) : base(texture, width, height) {
Initialize(width, height);
}
///
/// Create a new Spritemap from an AtlasTexture.
///
/// The AtlasTexture to use for the sprite sheet.
/// The width of a cell on the sprite sheet.
/// The height of a cell on the sprite sheet.
public Spritemap(AtlasTexture texture, int width, int height) : base(texture, width, height) {
Initialize(width, height);
}
}
}