Bagikan melalui


How to: Animate a Sprite

This article demonstrates how to animate a sprite from a texture using a custom class.

The source code in this example presumes that the texture being loaded is a strip of equal-sized images. In this example, the texture provided is a 256×64 texture with 4 frames.

To draw an animated sprite

  1. Follow steps 1–3 of How to: Draw a Sprite.

  2. In your game's constructor, create an instance of the AnimatedTexture class.

    private AnimatedTexture SpriteTexture;
    

public Game1() { ... SpriteTexture = new AnimatedTexture(Vector2.Zero, 0, 2.0f, 0.5f); }

  1. Load the texture or textures that provide the image data for the animation. In this example, the AnimatedTexture class loads a single texture and divides it into frames of animation. It uses the last parameter to determine how many frames to draw each second. In this case, it draws 4 frames at 2 fps (frames per second).

    private Viewport viewport;
    

private Vector2 shipPos; private SpriteBatch ForegroundBatch; protected override void LoadGraphicsContent( bool loadAllContent ) { if (loadAllContent) { // TODO: Load any ResourceManagementMode.Automatic content. ForegroundBatch = new SpriteBatch( graphics.GraphicsDevice );

    // "ship" is the name of the sprite asset in the project.
    SpriteTexture.Load( graphics.GraphicsDevice, content, "ship", 4, 2 );
    viewport = graphics.GraphicsDevice.Viewport;
    shipPos = new Vector2( viewport.Width / 2, viewport.Height / 2 );
}

// TODO: Load any ResourceManagementMode.Manual content.

}

  1. In your game's Update method, determine which frame of animation to display.

    protected override void Update( GameTime gameTime )
    

{ ...

// TODO: Add your update logic here.
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

// TODO: Add your game logic here.
SpriteTexture.UpdateFrame( elapsed );
base.Update( gameTime );

}

This is handled by AnimatedTexture's **UpdateFrame** method, which takes the elapsed seconds between updates as a parameter.

<pre IsFakePre="true" xmlns="http://www.w3.org/1999/xhtml">// class AnimatedTexture

public void UpdateFrame( float elapsed ) { if (Paused) return; TotalElapsed += elapsed; if (TotalElapsed > TimePerFrame) { Frame++; // Keep the Frame between 0 and the total frames, minus one. Frame = Frame % framecount; TotalElapsed -= TimePerFrame; } }

  1. In your game's Draw method, call Draw on the AnimatedTexture object.

    protected override void Draw( GameTime gameTime )
    

{ graphics.GraphicsDevice.Clear( Color.Black );

// TODO: Add your drawing code here.
ForegroundBatch.Begin();
SpriteTexture.DrawFrame( ForegroundBatch, shipPos );
ForegroundBatch.End();

base.Draw( gameTime );

}

**AnimatedTexture** will draw the sprite using the subrectangle of the texture that contains the desired animation.

<pre IsFakePre="true" xmlns="http://www.w3.org/1999/xhtml">// class AnimatedTexture

public void DrawFrame( SpriteBatch Batch, Vector2 screenpos ) { DrawFrame( Batch, Frame, screenpos ); } public void DrawFrame( SpriteBatch Batch, int Frame, Vector2 screenpos ) { int FrameWidth = myTexture.Width / framecount; Rectangle sourcerect = new Rectangle( FrameWidth * Frame, 0, FrameWidth, myTexture.Height ); Batch.Draw( myTexture, screenpos, sourcerect, Color.White, Rotation, Origin, Scale, SpriteEffects.None, Depth ); }

The Complete Example

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    ContentManager content;

    private AnimatedTexture SpriteTexture;
    public Game1()
    {
        graphics = new GraphicsDeviceManager( this );
        content = new ContentManager( Services );
        SpriteTexture = new AnimatedTexture(Vector2.Zero, 0, 2.0f, 0.5f);
    }


    protected override void Initialize()
    {
        // TODO: Add your initialization logic here.

        base.Initialize();
    }

    private Viewport viewport;
    private Vector2 shipPos;
    private SpriteBatch ForegroundBatch;
    protected override void LoadGraphicsContent( bool loadAllContent )
    {
        if (loadAllContent)
        {
            // TODO: Load any ResourceManagementMode.Automatic content.
            ForegroundBatch = new SpriteBatch( graphics.GraphicsDevice );

            // "ship" is the name of the sprite asset in the project.
            SpriteTexture.Load( graphics.GraphicsDevice, content, "ship", 4, 2 );
            viewport = graphics.GraphicsDevice.Viewport;
            shipPos = new Vector2( viewport.Width / 2, viewport.Height / 2 );
        }

        // TODO: Load any ResourceManagementMode.Manual content.
    }

    protected override void UnloadGraphicsContent( bool unloadAllContent )
    {
        if (unloadAllContent == true)
        {
            content.Unload();
        }
    }

    protected override void Update( GameTime gameTime )
    {
        // Allows the default game to exit on Xbox 360 and Windows.
        if (GamePad.GetState( PlayerIndex.One ).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // Pauses and plays the animation.
        if (GamePad.GetState( PlayerIndex.One ).Buttons.Start == ButtonState.Pressed)
        {
            if (SpriteTexture.IsPaused)
                SpriteTexture.Play();
            else
                SpriteTexture.Pause();
        }

        // TODO: Add your update logic here.
        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

        // TODO: Add your game logic here.
        SpriteTexture.UpdateFrame( elapsed );
        base.Update( gameTime );
    }

    protected override void Draw( GameTime gameTime )
    {
        graphics.GraphicsDevice.Clear( Color.Black );

        // TODO: Add your drawing code here.
        ForegroundBatch.Begin();
        SpriteTexture.DrawFrame( ForegroundBatch, shipPos );
        ForegroundBatch.End();

        base.Draw( gameTime );
    }
}

public class AnimatedTexture
{
    private int framecount;
    private Texture2D myTexture;
    private float TimePerFrame;
    private int Frame;
    private float TotalElapsed;
    private bool Paused;

    public float Rotation, Scale, Depth;
    public Vector2 Origin;
    public AnimatedTexture( Vector2 Origin, float Rotation, float Scale, float Depth )
    {
        this.Origin = Origin;
        this.Rotation = Rotation;
        this.Scale = Scale;
        this.Depth = Depth;
    }
    public void Load( GraphicsDevice device, ContentManager content, string asset, int FrameCount, int FramesPerSec )
    {
        framecount = FrameCount;
        myTexture = content.Load<Texture2D>( asset );
        TimePerFrame = (float)1 / FramesPerSec;
        Frame = 0;
        TotalElapsed = 0;
        Paused = false;
    }

    // class AnimatedTexture
    public void UpdateFrame( float elapsed )
    {
        if (Paused)
            return;
        TotalElapsed += elapsed;
        if (TotalElapsed > TimePerFrame)
        {
            Frame++;
            // Keep the Frame between 0 and the total frames, minus one.
            Frame = Frame % framecount;
            TotalElapsed -= TimePerFrame;
        }
    }

    // class AnimatedTexture
    public void DrawFrame( SpriteBatch Batch, Vector2 screenpos )
    {
        DrawFrame( Batch, Frame, screenpos );
    }
    public void DrawFrame( SpriteBatch Batch, int Frame, Vector2 screenpos )
    {
        int FrameWidth = myTexture.Width / framecount;
        Rectangle sourcerect = new Rectangle( FrameWidth * Frame, 0,
            FrameWidth, myTexture.Height );
        Batch.Draw( myTexture, screenpos, sourcerect, Color.White,
            Rotation, Origin, Scale, SpriteEffects.None, Depth );
    }

    public bool IsPaused
    {
        get { return Paused; }
    }
    public void Reset()
    {
        Frame = 0;
        TotalElapsed = 0f;
    }
    public void Stop()
    {
        Pause();
        Reset();
    }
    public void Play()
    {
        Paused = false;
    }
    public void Pause()
    {
        Paused = true;
    }

}

See Also

Tasks

How to: Draw a Sprite

Concepts

2D Graphics Overview

Reference

SpriteBatch
Draw
Texture2D