0
votes

I am working on an Animation class for XNA. I decided to try using extension methods for SpriteBatch to add Draw methods that can draw an AnimatedSprite.

AnimatedSprite contains a list of Sprite objects, and a Sprite object has a Texture2D image. I created a static Extensions class that contains different overloads of the Draw method.

Here's one such method (I assume the problem is similar for all the functions):

    public static void Draw(this SpriteBatch b, AnimatedSprite sprite, Vector2 position, Color color)
    {
        b.Draw(sprite.CurrentSprite.Image, position, color);
    }

I get a ArrayTypeMismatchException when I run my project. I am not sure what is causing it because sprite.CurrentSprite.Image is a Texture2D.

Hopefully someone will be able to help me understand what is causing this problem and a potential fix.

Thanks!

Update: AnimatedSprite Class

public class AnimatedSprite
{
    List<Sprite> frames;

    double elapsedSeconds;
    int currentIndex;

    /// <summary>
    /// CurrentSprite is the current frame the animation is on
    /// Use CurrentSprite.Image to get the underlying Texture2D
    /// </summary>
    public Sprite CurrentSprite { set; get; }
    /// <summary>
    /// FrameRate is the frame rate of the animation, measured
    /// in frames per second
    /// </summary>
    public int FrameRate { set; get; }

    bool shouldAnimate;

    /// <summary>
    /// Constructor for AnimatedSprite
    /// </summary>
    /// <param name="sprites">A list of sprites, cannot be left null</param>
    /// <param name="frameRate">The framerate in frames per second</param>
    /// <exception cref="ArgumentException">Thrown if sprites is null</Sprite></exception>
    public AnimatedSprite(List<Sprite> sprites, int frameRate)
    {
        if (sprites == null) throw new ArgumentException("Please provide a non-null List<Sprite>");
        this.frames = sprites;
        this.currentIndex = 0;
        if(this.frames.Count != 0) this.CurrentSprite = frames[currentIndex];

        this.FrameRate = frameRate;

        this.elapsedSeconds = 0;
    }

    /// <summary>
    /// Add a frame to the animation. It will be added to the end.
    /// </summary>
    /// <param name="frame">The Sprite you would like to add</param>
    public void AddFrame(Sprite frame)
    {
        frames.Add(frame);
        if (frames.Count == 1) this.CurrentSprite = frames[0];
    }

    /// <summary>
    /// Call this function in any Update method to continue the animation
    /// </summary>
    /// <param name="gameTime">The gameTime object keeping track of time</param>
    public void Update(GameTime gameTime)
    {
        elapsedSeconds += gameTime.ElapsedGameTime.TotalSeconds;
        if (elapsedSeconds > (1.0 / FrameRate) && shouldAnimate)
        {
            NextFrame();
            elapsedSeconds = 0;
        }
    }

    #region Animation Controls
    /// <summary>
    /// Starts the animation. This MUST be called to start the animation
    /// </summary>
    public void Start()
    {
        shouldAnimate = true;
    }
    /// <summary>
    /// Stops the animation. Call Start() to start again
    /// </summary>
    public void Stop()
    {
        shouldAnimate = false;
    }
    /// <summary>
    /// Advances the animation to the next cell
    /// </summary>
    public void NextFrame()
    {
        if (frames.Count == 0) return;
        currentIndex++;
        if (currentIndex >= frames.Count) currentIndex = 0;
        this.CurrentSprite = frames[currentIndex];
    }
    /// <summary>
    /// Advances the animation to the previous cell
    /// </summary>
    public void PreviousFrame()
    {
        if (frames.Count == 0) return;
        currentIndex--;
        if (currentIndex < 0) currentIndex = frames.Count - 1;
        this.CurrentSprite = frames[currentIndex];
    }
    #endregion Animation Controls
1
Could you post the AnimatedSprite Class please?Pidalia

1 Answers

0
votes

The only array used is sprite.CurrentSprite. This (i assume) uses the internal index you store in your animated sprite class to return the sprite at that index in the sprite array. Since this is the only place you use an array, this is your problem. As you haven't posted your AnimatedSprite class code, I can only suggest that you look at the property CurrentImage in your AnimatedSprite class and see if it accesses a Sprite[]. Please post the AnimatedSprite class so I can help you more.

Also, in my personal opinion, you should not be storing instances of the sprite class in AnimatedSprite, you should just store an array of textures. Storing an array of Sprite's implies that each of those sprites are separate entities, which they aren't; they are part of the same animated sprite.