大致步骤

动画播放的本质就是多张图片间的快速切换。每张图片都有单独的持续时间,即可根据播放进度选择一张图片显示出来。如果播放进度大于1(播放时间超过所有帧加起来的总时间)则从头来过。

1、创建AnimationFrame

首先创建AnimationFrame.cs文件

一个AnimationFrame就是动画中的其中一帧。这一帧可以是一整张包含所有帧的图片中的某个位置(Rectangle),也可以是单独的一张贴图(Texture2D),此处我选择后者(因为素材绘画的原因)。

using Microsoft.Xna.Framework.Graphics;
using System;

namespace CatFishing_Windows.Models
{
    class AnimationFrame
    {
        //帧贴图
        public Texture2D FrameTexture { get; set; }

        //帧持续时间
        public TimeSpan Duration { get; set; }
    }
}

2、创建Animation


创建Animation.cs文件,Animation中主要应该包含一下几项:

1、包含该动画所有帧的 List<Animation>

public List<AnimationFrame> Frames = new List<AnimationFrame>();

2、记录该动画从播放到现在的时间 TimeIntoAnimation

TimeSpan TimeIntoAnimation;

3、枚举每一帧的持续时间,累加获得动画持续的总时间 Duration

TimeSpan Duration
{
    get
    {
        double totalSeconds = 0;
        foreach (var frame in Frames)
        {
            totalSeconds += frame.Duration.TotalSeconds;
        }

        return TimeSpan.FromSeconds(totalSeconds);
    }
}

4、向Animation()添加帧的方法

public void AddFrame(Texture2D frame, double duration)
{
    AnimationFrame animationFrame = new AnimationFrame()
    {
        FrameTexture = frame,
        Duration = TimeSpan.FromSeconds(duration)
    };
    Frames.Add(animationFrame);
}

其中,frame为添加帧的贴图,duration为该帧的预计持续时间。duration之所以为double是为了让.Add()在调用时看起来没有那么冗长,将TimeSpan.FromSeconds()在传入.Add()后进行。

5、计算 TimeIntoAnimation 的方法 Update()。这个方法在game.cs内的update()处调用,每次update()时将gameTime.ElapsedGameTime.TotalSeconds累加进TimeIntoAnimation。

gameTime.ElapsedGameTime代表这次Update()距离上次Update()所耗的时间。

public void Update(GameTime gameTime)
{
    double secondsIntoAnimation =
        TimeIntoAnimation.TotalSeconds + gameTime.ElapsedGameTime.TotalSeconds;

    //用已播放的时间%动画总时间
    //若 已播放时间大于总时间 则余数是多出来的秒数,记录余数进入下一次循环
    //若 已播放时间小于总时间 则余数为 已播放时间
    double remainder = secondsIntoAnimation % Duration.TotalSeconds;

    TimeIntoAnimation = TimeSpan.FromSeconds(remainder);
}

6、获取当前时间的对应帧。逐帧累加时间,即可获知当前TimeIntoAnimation应该对应的帧。

public Texture2D CurrentTexture
{
    get
    {
        AnimationFrame currentFrame = null;

        // 逐帧查找对应的帧
        TimeSpan accumulatedTime = new TimeSpan();
        foreach (var frame in Frames)
        {
            if (accumulatedTime + frame.Duration >= TimeIntoAnimation)
            {
                currentFrame = frame;
                break;
            }
            else accumulatedTime += frame.Duration;
        }

        //如果无法找到帧 则返回最后一帧
        if (currentFrame == null)
            currentFrame = Frames.LastOrDefault();

        return currentFrame.FrameTexture;
    }
}
Summation

3、简单使用

1、创建新的Animation,并添加帧。

Animation a1 = new Animation();
a1.AddFrame(Content.Load<Texture2D>("png0"), 0.5);
a1.AddFrame(Content.Load<Texture2D>("png1"), 0.5);
a1.AddFrame(Content.Load<Texture2D>("png2"), 0.5);

2、在 game.cs中的Update()调用Animation的Update()事件

a1.Update(gameTime);

3、在game.cs中的Draw()绘制Animation的当前帧

spriteBatch.Draw(a1.CurrentTexture, new Vector2(0,0), Color.White);

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据