ImageVerifierCode 换一换
格式:DOC , 页数:12 ,大小:66.01KB ,
资源ID:185751      下载积分:15 文钱
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,省得不是一点点
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.wenke99.com/d-185751.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(XNA动画的实现4保存动画数据.DOC)为本站会员(天***)主动上传,文客久久仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知文客久久(发送邮件至hr@wenke99.com或直接QQ联系客服),我们立即给予删除!

XNA动画的实现4保存动画数据.DOC

1、 1 / 12 XNA动画的实现 4 保存动画数据 在上一篇文章中,我们实现了关键帧类实现了复杂的动画,这些复杂动画的数据都是在程序中手动生成的,为了能够重用这些数据,有必要实现下述功能:将动画数据保存为磁盘上的一个文件,使用时只要从 磁盘上读取这个文件构成动画数据类,就可以在内存中使用它了。 要做到这一点,只需使用 .NET框架的 文件 IO功能将动画数据文件串行化。 首先是关键帧数据类 Keyframe.cs,代码如下: / / 关键帧类,表示一个动画片段( AnimationClip)中一个指 定时刻的状态(包含位置、旋转、缩放信息), / 多个关键帧组成一个动画片段。 / public

2、 class Keyframe / / 位置 / public Vector3 Position get;set; / / 旋转 / public Vector3 Rotation get;set; / / 缩放 / public Vector3 Scale get;set; / / 此关键帧离开动画开始时刻的时间,单位为秒 / public double Time get;set; / / 创建一个关键帧 / public Keyframe(Vector3 Position, Vector3 Rotation, Vector3 Scale, double Time) this.Positio

3、n = Position; 2 / 12 this.Rotation = Rotation; this.Scale = Scale; this.Time = Time; / 必须要有一个不带参数的构造 函数用于串行化 private Keyframe() 这个代码与上一篇文章几乎是一样的,但有三点不同: 1 各个属性由原来的只读变成可写,这样做破坏了类的封装性,让用户可以设置属性值,从而导致错误。但是要让这个类可串行化,属性必须可写。 2 Time属性由原来的 TimeSpan类型变成了 double类型。这是因为 .NET框架无法串行化 TimeSpan 类型,导出为空值,所以只能换种类型。

4、下一篇文章的方法可以解决这个问题 。 3 必须要有一个不带参数的构造函数,否则串行化 过程会报错 。 然后是动画数据类 AnimationClip.cs,你需要将数据和方法分离,因此,相对于上一篇文章,这个类删除了方法,只保留了数据,变得简单多了。代码如下: / / 动画片段类,这个类保存一个关键帧集合和动画持续时间。 / public class AnimationClip / / 动画片段的播放长度 / public double Duration get; set; / / 关键帧集合 / public List Keyframes get; set; / / 创建一个动画片段 / /

5、关键帧集合 public AnimationClip(List Keyframes) this.Keyframes = Keyframes; /对关键帧根据时间先后进行排序 Keyframes.Sort(CompareKeyframeTimes); / 动画播放的时间就是最后一个关键帧的 Time属性 3 / 12 this.Duration = KeyframesKeyframes.Count - 1.Time; / / 创建一个动画片段 ,数据是从一个 xml文件加载的 / public AnimationClip(string fileName) / - / 下述代码应该还有改进空间 /

6、 - AnimationClip animationData; / 将 xml文件反串行化获取动画数据 using (XmlReader reader = XmlReader.Create(fileName) XmlSerializer serializer = new XmlSerializer(typeof(AnimationClip); animationData = (AnimationClip)serializer.Deserialize(reader); this.Keyframes = animationData.Keyframes; /对关键帧根据时间先后进行排序 Keyfra

7、mes.Sort(CompareKeyframeTimes); / 动画播放的时间就是最后一个关键帧的 Time属性 this.Duration = KeyframesKeyframes.Count - 1.Time; / 必须要有一个不带参数的构造函数用于串行化 private AnimationClip() / 按照关键帧的时间属性升序排序的 Comparison方法 int CompareKeyframeTimes(Keyframe a, Keyframe b) return a.Time.CompareTo(b.Time); 从代码中我们可以看出 ,首先我们在 AnimationCli

8、p 中添加了一个表示动画持续时间的Duration 属性,它实际上就是关键帧数组中最后一个的时间 Time 属性 , 将它提取 出来可以简化后面的操作 。 而且我们还编写了一个以动画数据名称为参数的构造函数,在这个构造函数中,我们使用了 IO功能从磁盘的动画数据 xml文件中读取了信息构建了 AnimationClip类。 而原来的 AnimationClip 类中的方法移至一个新的类中,我命名为 AnimationPlayer,它负责计算变换矩阵, 控制动画的播放。代码如下: 4 / 12 / / 控制动画播放的类,这个类负责计算变换矩阵,还可以调整动画播放的速度 / public clas

9、s AnimationPlayer private AnimationClip animationClip; / 动画片段 TimeSpan startTime, endTime; / 动画播放开始时刻和结束时刻 TimeSpan elapsedTime; / 动画当前已经播放的时间 int currentKeyframeIndex; / 动画当前播放的关键帧索引 bool loop; / 动画是否循环 float playbackRate = 1.0f; / 动画播放倍率, 1表示正常速度播放 LerpMode lerpMode; / 动画数据的插值模式 Vector3 position,

10、rotation, scale; / 当前时刻的位置、旋转和缩放 / / 动画是否已经播放完成 / public bool Done get; private set; / / 动画是否处于暂停状态 / public bool Paused get; set; / / 变换矩阵 / public Matrix Transform get; private set; / / 创建一个动画播放类 / / 要播放的动画片段 public AnimationPlayer(AnimationClip setAnimationClip) this.animationClip = setAnimationC

11、lip; / / 更新动画数据 5 / 12 / public void Update(GameTime gameTime) if (animationClip = null | Done) return; if (Paused) return; TimeSpan time = gameTime.ElapsedGameTime; / 调整动画播放速度 if (playbackRate != 1.0f) time = TimeSpan.FromSeconds(time.TotalSeconds * playbackRate); elapsedTime += time; / 进行插值操作 upda

12、teTransforms(); void updateTransforms() / 如果动画播放的时间已经超过指定的时间间隔 . while (elapsedTime = (endTime - startTime) / 如果是循环动画,则将动画播放时间回退到 0 if (loop) elapsedTime -= (endTime - startTime); currentKeyframeIndex = 0; / 否则,将播放时间进行截取 else Done = true; elapsedTime = endTime - startTime; break; / 读取 关键帧集合 IList ke

13、yframes = animationClip.Keyframes; / 首先获取离开整个动画开始时刻的时间,然后根据它获取当前关键帧的索引 / 最后获取从当前帧开始的动画播放时间,这个才能根据这个时间进行插值运算 double totalTime = (elapsedTime+ startTime).TotalSeconds; 6 / 12 while (keyframescurrentKeyframeIndex + 1.Time max) 7 / 12 value -= max; while (value / 播放完整的动画片段 / / 是否循环播放 / 变换插值模式 / 动画播放倍率 p

14、ublic void StartClip(bool loop,LerpMode lerpMode,float playbackRate) StartClip(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(animationClip.Duration), loop, lerpMode, playbackRate); / / 根据给定的关键帧索引播放两关键帧之间的动画片段 / / 开始时刻的关键帧索引 / 结束时刻的关键帧索引 / 是否循环播放 / 变换插值模式 / 动画播放倍率 public void StartClip(int startFrame

15、, int endFrame, bool loop,LerpMode lerpMode,float playbackRate) StartClip(TimeSpan.FromSeconds (animationClip.KeyframesstartFrame.Time), TimeSpan.FromSeconds (animationClip.KeyframesendFrame.Time), loop,lerpMode,playbackRate); / / 根据给定的开始时刻和结束时刻播放一段时间内的动画片段 / / 开始时刻 / 结束时刻 / 是否循环播放 / 变换插值模式 / 动画播放倍率

16、 8 / 12 public void StartClip(TimeSpan StartTime, TimeSpan EndTime, bool loop, LerpMode lerpMode,float playbackRate) this.startTime = StartTime; this.endTime = EndTime; this.loop = loop; this.lerpMode = lerpMode; this.playbackRate =playbackRate; elapsedTime = TimeSpan.FromSeconds(0); currentKeyframe

17、Index = 0; / / 暂停播放 / public void PauseClip() Paused = true; / / 继续播放 / public void ResumeClip() Paused = false; 代码较长,但核心代码的原理与上一章是类似的。上一章只能播放完整的动画,而改进的代码可以根据输入的参数播放部分动画 。 动画数据文件的创建 现在的问题是:存储动画数据的 xml 文件从何而来?你可以在 XNA 代码中使用串行化将 AnimationClip类保存为 xml文件。 首先在 XNA主类中添加一个 AnimationClip变量,然后在 Initialize()方

18、法中使用第一个构造函数初始化这个类: protected override void Initialize() 9 / 12 List keyframes = new List(); / 以下这组关 键帧使物体绕一个三角形运动 keyframes.Add(new Keyframe(new Vector3(-16, 0, 16), new Vector3(0, MathHelper.ToRadians(0), 0), * Vector3.One, 0); keyframes.Add(new Keyframe(new Vector3(16, 0, 16), new Vector3(0, MathH

19、elper.ToRadians(90), 0), * Vector3.One, 3); keyframes.Add(new Keyframe(new Vector3(0, 0, -16), new Vector3(0, MathHelper.ToRadians(180), 0), * Vector3.One, 6); keyframes.Add(new Keyframe(new Vector3(-16, 0, 16), new Vector3(0, MathHelper.ToRadians(0), 0), * ector3.One, 9); animation = new AnimationC

20、lip(keyframes); base.Initialize(); 然后在 Update方法中编写如下代码: protected override void Update(GameTime gameTime) / 按下数字键 1将动画数据串行化为一个 xml文件 if (IsNewKeyPress(Keys.D1) / 设置将 xml元素缩进,便于阅读 XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; using (XmlWriter writer = XmlWriter.Create(“E:/AnimationData.xml“, settings) XmlSerializer serializer = new XmlSerializer(typeof(AnimationClip); serializer.Serialize(writer, animation); base.Update(gameTime); 运行 XNA程序,然后按下数字键 1,你就会在 E盘根目录下找到一个名为 AnimationData的 xml文件,看看它的内容: 10 / 12 9 -16 0 16 0 0 0 1 1 1 0 16 0 16 0 1.57079637 0 1 1 1 3

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。