一直在想应该用什么作为《Silverlight 2.5D RPG游戏技巧与特效处理系列教程》的终结,既要实用而不拖泥带水;又要通用而不哗众取宠。于是一不小心便成就了我一个未了心愿:一切基于动态绘制路径而生成的万象动画作为这又一部作品的谢幕,足矣。

还记得我们小时候玩的《坦克大战》、《雷电》吗?在那狭小的弹粒缝隙间躲闪追逐成为了每每课后最快乐的回忆:

还记得高三那年的春天吗?每次丢下书包第一时间总会跑进网吧与同学们联网《星级争霸》、《帝国时代》;4V4、罗马战车VS投石车,炮火与弓箭的洗礼下,我们幸福的青春就这样被无限的释放:

大学里,《博德之门》、《奇迹》、《半条命》、《破碎银河系》等N多顶级游戏/网游让我短暂的忘却了时代赋予大学生的苦闷,人生除了现实,其实成为一名虚拟的王者未必不是今生一件幸事。“魔法飞弹”横空掠过、“蓝翎弩”三重穿梭、“手雷”华丽的抛物线、“跟踪弹”锲而不舍的精神如同网吧中弥漫着无上团结的凝聚力,走过了4年,也走过了最让我留念和感动的“兄弟年代”:

直至今日,当我们坐在凳子上开始编写属于自己的游戏时,当年战斗的画面早已模糊不清,残留的仅剩无数的弹粒在天空中你来我往,毫无眷恋。一直在想是否能够通过一块画板外加几个选项来完成所有一切的自定义路径动画,从而让游戏设计中那些如此神秘而又变幻莫测的“弹道轨迹”变得简单而轻松?

之前便有很多人公开了他们的相关成果,关于Silverlight中的路径动画(Path Animation)实现,比如下面两个链接:

http://www.codeproject.com/KB/silverlight/PathAnimation.aspx

http://geekswithblogs.net/cskardon/archive/2010/09/21/path-animation-in-silverlight.aspx

很可惜它们均为外国人所作,第一篇重新封装了一个名为PathAnimation的类,基于Blend绘制Path坐标数据实现路径动画;而后者则完全是通过Blend绘制的路径动画。虽然均能达到效果,但易用性及拓展性显然不够强。想想,怎样的自定义路径动画才能最大化适应当下绝大多数(各类型)游戏的需要?尤其在RPG游戏中,能为之增添无限乐趣和优秀的玩家视觉体验。

思路再一次回到那块画板上,通过鼠标在画板上移动,然后将鼠标所经过的轨迹以一定的密度绘制在其上并按顺序保存到List<Point>中,最后通过Storyboard的关键帧动画将所有的Point连成一个完整的路径动画。其中通过简单的顺时针/逆时针判断公式及匀加/减速度计算公式(任何公式都可以随意拓展)来分别实现动画延路径移动时的动态朝向及变速运动效果;当然,再配合上坐标缩放系数,从而最终整个自定义路径动画所实现的效果可完美无缝的移植到任何有相关需求的Silverlight游戏中:

弹粒的关键帧动画

                        Bullet bullet  =   new  Bullet( new  BulletDatas() { Code  =  pathAnimationPainter[n].AnimationCode, Loop  =   true , Type  =  BulletTypes.Animation }) { Z  =   100  };
                        bullet.Center  =  bullet.Offset;
                        tabCanvas2.Children.Add(bullet);
                        Storyboard storyboard  =   new  Storyboard();
                        PointAnimationUsingKeyFrames pointAnimationUsingKeyFrames  =   new  PointAnimationUsingKeyFrames();
                        Storyboard.SetTarget(pointAnimationUsingKeyFrames, bullet);
                        Storyboard.SetTargetProperty(pointAnimationUsingKeyFrames,  new  PropertyPath( " Position " ));
                        DoubleAnimationUsingKeyFrames doubleAnimationUsingKeyFrames  =   new  DoubleAnimationUsingKeyFrames();
                        Storyboard.SetTarget(doubleAnimationUsingKeyFrames, bullet);
                        Storyboard.SetTargetProperty(doubleAnimationUsingKeyFrames,  new  PropertyPath( " Angle " ));
                         double  speed  =  pathAnimationPainter[n].Rate;
                         double  a  =   0.002 ;  // 加速系数
                         double  timeSpanTemp  =   ;
                         double  durationTemp  =   ;
                         double  angleTemp  =   ;
                         int  circle  =   ;
                         if  (pathAnimationPainter[n].Easing  ==   2 ) {   // 加速逆行即减速
                             for  ( int  i  =   ; i  <  pathAnimationPainter[n].Path.Count; i ++ ) 
                            { speed  +=  a  *  i; } 
                        }
                         for  ( int  i  =   ; i  <  pathAnimationPainter[n].Path.Count; i ++ ) {
                            TimeSpan timeSpan  =   new  TimeSpan();
                            Point lastPath  =  (i  ==     ?  pathAnimationPainter[n].Path[ ] : pathAnimationPainter[n].Path[i  -   1 ]);
                            Point nowPath  =  pathAnimationPainter[n].Path[i];
                            Point nextPath  =  (i  ==  pathAnimationPainter[n].Path.Count  -   1   ?  pathAnimationPainter[n].Path[pathAnimationPainter[n].Path.Count  -   1 ] : pathAnimationPainter[n].Path[i  +   1 ]);
                             switch  (pathAnimationPainter[n].Easing) {
                                 case   :
                                    timeSpanTemp  =  GlobalMethod.GetDistance(lastPath, nowPath)  /  speed;
                                    durationTemp  +=  timeSpanTemp;
                                    timeSpan  =  TimeSpan.FromMilliseconds(durationTemp);
                                     break ;
                                 case   1 :
                                    speed  +=  a  *  i;
                                    timeSpanTemp  =  GlobalMethod.GetDistance(lastPath, nowPath)  /  speed;
                                    durationTemp  +=  timeSpanTemp;
                                    timeSpan  =  TimeSpan.FromMilliseconds(durationTemp);
                                     break ;
                                 case   2 :
                                    speed  -=  a  *  (pathAnimationPainter[n].Path.Count  -   1   -  i);
                                    timeSpanTemp  =  GlobalMethod.GetDistance(lastPath, nowPath)  /  speed;
                                    durationTemp  +=  timeSpanTemp;
                                    timeSpan  =  TimeSpan.FromMilliseconds(durationTemp);
                                     break ;
                            }
                            pointAnimationUsingKeyFrames.KeyFrames.Add(
                                 new  LinearPointKeyFrame() {
                                    KeyTime  =  KeyTime.FromTimeSpan(timeSpan),
                                    Value  =   new  Point() { X  =  nowPath.X  *  pathAnimationPainter[n].Proportion, Y  =  nowPath.Y  *  pathAnimationPainter[n].Proportion }
                                }
                            );
                             double  angle  =  GlobalMethod.GetAngle(nowPath.Y  -  lastPath.Y, nowPath.X  -  lastPath.X)  +   360   *  circle;
                             // check大于0为顺时针个方向
                             double  check  =  (nowPath.X  -  lastPath.X)  *  (nextPath.Y  -  nowPath.Y)  -  (nowPath.Y  -  lastPath.Y)  *  (nextPath.X  -  nowPath.X);
                             if  (check  >   ) {
                                 if  (angleTemp  >   360   *  circle  &&  angle  <   360   *  circle) { angle  +=   360 ; }  else   if  (angleTemp  >   360   *  circle  +   180   &&  angle  <  angleTemp) { angle  +=   360 ; circle ++ ; }
                            }  else  {
                                 if  (angleTemp  <   360   *  circle  &&  angle  >   360   *  circle) { angle  -=   360 ; }  else   if  (angleTemp  <   360   *  circle  -   180   &&  angle  >  angleTemp) { angle  -=   360 ; circle -- ; }
                            }
                            angleTemp  =  angle;  // 用于旋转时的角度衔接
                            doubleAnimationUsingKeyFrames.KeyFrames.Add(
                                 new  LinearDoubleKeyFrame() {
                                    KeyTime  =  KeyTime.FromTimeSpan(timeSpan),
                                    Value  =  angle
                                }
                            );
                        }
                        pointAnimationUsingKeyFrames.Duration  =   new  Duration(TimeSpan.FromMilliseconds(durationTemp));
                        storyboard.Children.Add(pointAnimationUsingKeyFrames);
                         if  (pathAnimationPainter[n].Direction  ==   ) { storyboard.Children.Add(doubleAnimationUsingKeyFrames); }
                        EventHandler handler  =   null ;
                        storyboard.Completed  +=  handler  =   delegate  {
                            storyboard.Completed  -=  handler;
                            tabCanvas2.Children.Remove(bullet);
                            bullet.Move_Completed(bullet,  null );
                        };
                        storyboard.Begin();

还在羡慕《倩女幽魂Online》交织穿梭的吸血法术吗?

还在嫉妒《星辰变》中的移动粒子施法吗?还在恨2D/2.5D无法实现类似3D游戏中那些高随意性的路径动画吗?

有了本节的自定义路径动画攻略,大家只需一个描述路径的List<Point>,配合上几个参数而已,一切效果随手创造:

看到这你是否开始心动了?没错,尤其是在角色位置相对固定的回合制、SLG等类型游戏中,在发动者与它的目标之间创造出你认为最华丽的路径,无论魔法的走位还是角色的各类移动等效果都将变得轻而易举,这就是Silverlight给我们游戏开发者所带来的奇迹~!

Silverlight 时代即将来临,您准备好了吗?

本系列源码请到目录中下载

在线演示地址:http://silverfuture.cn

原文链接: http://www.cnblogs.com/alamiye010/archive/2011/06/29/2093568.html

转载于:https://my.oschina.net/chen106106/blog/43590

Silverlight 2.5D RPG游戏技巧与特效处理:(二十一)自定义路径动画相关推荐

  1. Silverlight 2.5D RPG游戏技巧与特效处理:(七)动画特写

    Silverlight中的HLSL不仅适用于场景与动画渲染,对于游戏中的角色,我们同样可以利用它制作动画特写.较常见的比如角色传送时的淡入淡出.扭曲变形.幻化呈现等切换动画,当然还有例如角色被DeBu ...

  2. 一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(七)动画特写

    Silverlight中的HLSL不仅适用于场景与动画渲染,对于游戏中的角色,我们同样可以利用它制作动画特写.较常见的比如角色传送时的淡入淡出.扭曲变形.幻化呈现等切换动画,当然还有例如角色被DeBu ...

  3. Silverlight 2.5D RPG游戏技巧与特效处理(Game Effects):目录

    以当下主流的2.5D RPG客户端品质游戏特效为借鉴,以最大程度控制性能损失为前提,将Silverlight游戏资源占用最小化,综合效果及用户体验最优化,即本系列作者想要向大家讲解的核心技术知识. 本 ...

  4. Silverlight 2.5D RPG游戏技巧与特效处理:自定义路径动画

    一直在想应该用什么作为<Silverlight 2.5D RPG游戏技巧与特效处理系列教程>的终结,既要实用而不拖泥带水:又要通用而不哗众取宠.于是一不小心便成就了我一个未了心愿:一切基于 ...

  5. Silverlight 2.5D RPG游戏技巧与特效处理:(十一)AI系统

    Silverlight 2.5D RPG游戏技巧与特效处理:(十一)AI系统 作者: 深蓝色右手  来源: 博客园  发布时间: 2011-04-19 11:18  阅读: 1282 次  推荐: 0 ...

  6. Silverlight 2.5D RPG游戏技巧与特效处理:(五)HLSL渲染动画

    或许大家依旧对上一节中的"黑夜"及"梦回过去"记忆犹新,追问下去HLSL到底是何方神圣能实现如此炫酷之效果?HLSL(高级着色器语言)作为微软的独门兵器,仅供D ...

  7. Silverlight 2.5D RPG游戏技巧与特效处理:HLSL渲染动画

    或许大家依旧对上一节中的"黑夜"及"梦回过去"记忆犹新,追问下去HLSL到底是何方神圣能实现如此炫酷之效果?HLSL(高级着色器语言)作为微软的独门兵器,仅供D ...

  8. 一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(五)圣赞之HLSL渲染动画...

    或许大家依旧对上一节中的"黑夜"及"梦回过去"记忆犹新,追问下去HLSL到底是何方神圣能实现如此炫酷之效果?HLSL(高级着色器语言)作为微软的独门兵器,仅供D ...

  9. Silverlight 2.5D RPG游戏技巧与特效处理:(十二)魔法系统

    全球首款Silverlight – MMORPG:<<窝窝世界>>震撼登场!伴着与XNA合体后的Silverlight 5 强势发布,一波Silverlight网游研发海啸即将 ...

最新文章

  1. MySQL中的联合查询
  2. CentOS基础命令大全
  3. highCharts文档与演示效果的使用 - 文档(应用型)解读
  4. 04 能够使用String类常用方法操纵字符串 0214
  5. Centos7中修改Hostname的方法
  6. 拓端tecdat|卡尔曼滤波器:用R语言中的KFAS建模时间序列
  7. disruptor:CAS实现高效(伪)无锁阻塞队列实践
  8. Bookshelf 2 POJ - 3628(01背包||DFS)
  9. X11/XWINDOW GUI窗口应用在任务栏上没有显示的解决办法
  10. 使用Sublime Text 2 编辑Markdown
  11. java多线程Thread.sleep方法用法详解
  12. redhat 5安装mysql_如何在redhat linux advancex 上安装mysql5
  13. java与数据库连接实验报告_数据库原理与应用java实验报告
  14. 期末考试-第一章-计算机视觉综述知识整理
  15. Linux安全模块(LSM)
  16. EasyTalking微博系统
  17. 人体的神经系统图 分布,人神经系统分布图高清
  18. 捋一捋Kafka中的消费者API
  19. RIGHT-BICEP单元测试——“二柱子四则运算升级版”
  20. draft伦理——第六章

热门文章

  1. SWUST OJ1168喝可乐
  2. 计算机科学是怎样的一个专业?
  3. 冯诺依曼机核心由运算器转变为存储器的原因
  4. python考试等级划分_考试等级分类
  5. 【区块链 | 智能合约】Ethereum源代码 - 智能合约地址生成算法
  6. 从苹果IOS14的App Library分类看用户行为与使用需求
  7. Java五子棋-人人对战
  8. EXCEL常见问题五十问题解答
  9. 软件测试工程师职业发展路线简介
  10. 教师招聘 计算机技能测试,技能测试-计算机(教师招考真题).doc