using System;
namespace MonoGame.Extended.Tilemaps
{
///
/// Represents a frame-based animation for a tile.
///
public class TilemapTileAnimation
{
private int _currentFrameIndex;
private float _elapsedTime;
///
/// Gets the animation frames.
///
public TilemapTileAnimationFrame[] Frames { get; }
///
/// Gets the total duration of the animation in seconds.
///
public float TotalDuration
{
get
{
float total = 0;
foreach (var frame in Frames)
{
total += frame.Duration;
}
return total;
}
}
///
/// Gets the current frame index.
///
public int CurrentFrameIndex
{
get
{
return _currentFrameIndex;
}
}
///
/// Gets the current frame.
///
public TilemapTileAnimationFrame CurrentFrame
{
get
{
return Frames[_currentFrameIndex];
}
}
///
/// Initializes a new instance of the class.
///
/// The animation frames.
public TilemapTileAnimation(TilemapTileAnimationFrame[] frames)
{
Frames = frames;
}
///
/// Updates the animation.
///
/// The time elapsed since the last update, in seconds.
public void Update(float deltaTime)
{
if (Frames.Length == 0)
{
return;
}
_elapsedTime += deltaTime;
// Advance frames based on elapsed time
while (_elapsedTime >= Frames[_currentFrameIndex].Duration)
{
_elapsedTime -= Frames[_currentFrameIndex].Duration;
_currentFrameIndex = (_currentFrameIndex + 1) % Frames.Length;
}
}
public TilemapTileAnimationFrame GetFrameAtTime(float time)
{
if (Frames.Length == 0)
{
throw new InvalidOperationException("Animation has no frames");
}
// Wrap time within total duration
float totalDuration = TotalDuration;
if (totalDuration <= 0)
{
return Frames[0];
}
time = time % totalDuration;
if (time < 0)
{
time += totalDuration;
}
// Find the frame at this time
float accumulated = 0;
foreach (var frame in Frames)
{
accumulated += frame.Duration;
if (time < accumulated)
{
return frame;
}
}
// Should never reach here, but return last frame as fallback
return Frames[Frames.Length - 1];
}
///
/// Resets the animation to the first frame.
///
public void Reset()
{
_currentFrameIndex = 0;
_elapsedTime = 0;
}
}
}