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; } } }