大致步骤
动画播放的本质就是多张图片间的快速切换。每张图片都有单独的持续时间,即可根据播放进度选择一张图片显示出来。如果播放进度大于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);