一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(九)粒子系统

  粒子系统通常用于三维场景中进行真实环境模拟,比如第四节的天气系统。天气的实现是粒子系统最重要的应用领域之一,所有的一切无论是云、雨、雾,还是落叶、陨石及闪电,都可视作基础粒子;除此之外,游戏中常常还会用到粒子系统来渲染像发光、轨迹等抽象效果。当然,有时简单并不意味着就不能缔造奇迹,比如本节大家将要看到的就是基于简单粒子系统所创建的当下主流2.5D RPG中极其拉风之装备粒子发散动画特效。

   一提到Silverlight中的粒子,首先想到的肯定是WriteableBitmap。没错,今天的主角就是它,让人又爱又恨的WriteableBitmap。爱,因为它可以对Silverlight中任意UI对象进行基于像素级别的处理,这意味着只要想得出的效果肯定能实现;正因如此,对其恨之入骨则因为WriteableBitmap在目前的版本中还暂时无法得到GPU硬件加速的支持,其功能偏少,性能也有待进一步提高。

  仅当为了Silverlight 5 的登场打基础,借鉴《降龙之剑》中的装备粒子系统,我们同样可以通过非常简单的代码编写出极度拉风的粒子发射动画特效。

  于是我们得首先准备基础粒子素材,比如希望武器会冒着火光,亦或者你希望铠甲能寒冰四散等,那么我们每样准备3张或更多的图片,通过随即的方式呈现便可达到相当逼真的效果:

  接下来的问题是这些粒子该如何以精确的装备部件实体区域为起点进行发射?

  用WriteableBitmap对每帧图片进行宽*高数量像素的逐个扫描?试想如果角色的尺寸是500*500=250000,那么每间隔几百毫秒都要遍历几十万的像素,UI线程不卡死才怪(顺便提一下,UI卡死的罪魁祸首就是循环,在UI线程中应尽量减少循环次数或巧妙的进行分解与规避)。其实我们完全可以采用随机抽样的方案,比如每次对其中的1000个像素进行抽样检查,当其A值(透明度)不为0时则表示该像素正处于装备部件的实体区域中。接下来便可仿造流光追影的类似效果,通过WriteableBitmap对目标装备部件首先进行复制,然后按照如上方式随机抽取部分装备实体上的粒子进行发射飘散:


/// <summary>
/// 显示风中粒子
/// </summary>
/// <param name="role">所修饰角色</param>
/// <param name="equipType">所参照的装备</param>
/// <param name="particleType">粒子类型</param>
/// <param name="color">颜色</param>
/// <param name="amount">量</param>
public void ShowWindParticles(Hero role, EquipTypes equipType, ParticleTypes particleType, Color color, double amount) {
int distance = 0;
double speed = 0;
if (role.Action == Actions.Stop) {
distance = 40;
speed = RandomSeed.Next(2000, 3000) * 0.01;
} else {
distance = 40;
speed = RandomSeed.Next(1000, 1500) * 0.01;
}
int halfDistance = distance / 2;
int obliqueDistance = distance * 2 / 3;
string particleName = string.Empty;
switch (particleType) {
case ParticleTypes.Normal:
particleName = "Particle";
break;
case ParticleTypes.Smoke:
particleName = "Smoke";
break;
case ParticleTypes.Ice:
particleName = "Ice";
break;
case ParticleTypes.Spark:
particleName = "Spark";
break;
}
Dispatcher.BeginInvoke(delegate {
ObjectBase equip = role.EquipEntity(equipType);
WriteableBitmap writeableBitmap = new WriteableBitmap(equip, null);
lock (writeableBitmap) {
writeableBitmap.Invalidate();
int z = 0;
if (equipType == EquipTypes.Weapon) {
z = role.Z + equip.Z;
} else {
z = (role.Direction == Directions.North || role.Direction == Directions.NorthEast || role.Direction == Directions.NorthWest) ? role.Z : role.Z - 20;
}
Point position = equipType == EquipTypes.Overall ? role.Center : equip.Position;
Point2D destination = new Point2D();
MonoChrome monoChrome = new MonoChrome() { FilterColor = color };
switch (role.Direction) {
case Directions.North:
destination.X = 0; destination.Y = RandomSeed.Next(halfDistance, distance);
break;
case Directions.NorthEast:
destination.X = -RandomSeed.Next(halfDistance, obliqueDistance); destination.Y = RandomSeed.Next(halfDistance, obliqueDistance);
break;
case Directions.East:
destination.X = -RandomSeed.Next(halfDistance, distance); destination.Y = 0;
break;
case Directions.SouthEast:
destination.X = -RandomSeed.Next(halfDistance, obliqueDistance); destination.Y = -RandomSeed.Next(halfDistance, obliqueDistance);
break;
case Directions.South:
destination.X = 0; destination.Y = -RandomSeed.Next(halfDistance, distance);
break;
case Directions.SouthWest:
destination.X = RandomSeed.Next(halfDistance, obliqueDistance); destination.Y = -RandomSeed.Next(halfDistance, obliqueDistance);
break;
case Directions.West:
destination.X = RandomSeed.Next(halfDistance, distance); destination.Y = 0;
break;
case Directions.NorthWest:
destination.X = RandomSeed.Next(halfDistance, obliqueDistance); destination.Y = RandomSeed.Next(halfDistance, obliqueDistance);
break;
}
for (int i = 0; i < amount; i++) {
int x = RandomSeed.Next(0, writeableBitmap.PixelWidth);
int y = RandomSeed.Next(0, writeableBitmap.PixelHeight);
byte[] bytes = BitConverter.GetBytes(writeableBitmap.Pixels[writeableBitmap.PixelWidth * y + x]);
if (bytes[3] != 0) {
Particle particle = new Particle() { Effect = monoChrome, Z = z, Source = GlobalMethod.GetProjectImage(string.Format("UI/{0}{1}.png", particleName, RandomSeed.Next(0, 3))) };
space.Children.Add(particle);
EventHandler handler = null;
particle.Disposed += handler = (s, e) => {
Particle p = s as Particle;
p.Disposed -= handler;
space.Children.Remove(p);
};
particle.Move(new Point(role.Position.X - position.X + x, role.Position.Y - position.Y + y), new Point(role.Position.X - position.X + x + destination.X, role.Position.Y - position.Y + y + destination.Y), speed, MoveModes.Opacity);
}
}
}
});
}

  其中,根据角色的动作状态以及当前的朝向,粒子在场景中的层次关系、移动速度,发散面积以及路径等均应体现出差异;比如站立时粒子流动稍微慢些、贴身些,而当角色移动时模拟迎风的效果,粒子飘散则呈加速趋势;另外,骑马奔驰时因地面的凹凸跌宕也应塑造出粒子群散呈现起伏波动之势等等:

  WriteableBitmap与HLSL是Silverlight中的两把神器,特别是在制作动画及特效方面尤显突出,只要你的算法够强,无论是采用C#还是HLSL,均可实现一切想要的特效动画。虽然两者目前的共同问题都出在性能上,如此这些华丽而炫酷的动画特效使我更饥渴的期待Silverlight 5降临的那天,当新的传奇上演之刻起,历史将被彻底的改写!

  本节源码下载地址:Demo8.rar

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

时间: 2024-10-19 23:40:01

一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(九)粒子系统的相关文章

一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(四)天气系统

如同动态光影一样,天气系统同样为2.5D RPG游戏所不可或缺的元素之一.从视觉角度讲,天气系统让游戏场景空间层次分明,立体感更强:从用户角度讲,天气系统赋予游戏更贴近现实的亲历体验,试想下游戏中的花花草草随风而动,云雾缭绕风雨雷电一切来得自然而平滑,玩家即似身临其境般享受:从功能角度讲,不同的气候状况会对角色及魔法效果产生各异影响,极大的提升游戏趣味性.  模拟相对较真实的天气效果,粒子系统必不可少,天气中的雨.雪.闪电.云雾等均可看做是大量粒子的集合.因此首先我们新建一个名为Particle

Silverlight 2.5D RPG游戏技巧与特效处理:“.NET研究”(四)天气系统

如同动态光影一样,天气系统同样为2.5D RPG游戏所不可或缺的元素之一.从视觉角度讲,天气系统让游戏场景空间层次分明,立体感更强:从用户角度讲,天气系统赋予游戏更贴近现实的亲历体验,试想下游戏中的花花草草随风而动,云雾缭绕风雨雷电一切来得自然而平滑,玩家即似身临其境般享受:从功能角度讲,不同的气候状况会对角色及魔法效果产生各异影响,极大的提升游戏趣味性.  模拟相对较真实的天气效果,粒子系统必不可少,天气中的雨.雪.闪电.云雾等均可看做是大量粒子的集合.因此首先我们新建一个名为Particle

一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(二)纸娃娃系统

纸娃娃系统,或许大家听起来并不陌生.早在十几年前,当时不论是文字游戏"泥巴(Mud)"或是交友.社交网站,我们只能通过屏幕上的文字来传达与交互信息:随着技术不断进步,2D/3D图形技术高速崛起,通过在基础模型上由客户随意挑选.任意更换各种造型(素材),即可打造出真正属于"自我"独特风格的网络虚拟形象,QQ秀便是我们耳熟能详的代表,更贴近真实的如(RPG)游戏及虚拟现实中的换装/换肤系统同样亦得益于纸娃娃机制. 本节,我将向大家讲解如何最好的实现Silverlight

一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(三)动态光影

通常来说,只要谈到影子及影子制作,首先想到的不外乎3D.游戏中的影子设计大致可分为硬实现和软实现两种,比如像"游戏影子制作技术"这篇文章所谈到3D游戏影子制作方案Projective Shadow.Shadow Map以及Shadow Volume均属于硬实现.硬实现的效果最逼真,相对的运算量也较高:而对于Silverlight开发2.5D网游来说,我们通常会采用折中的软实现去表述场景中的动态光影效果.精致的光影能让玩家充分体验到空间立体感,当然也是2.5D网游所不可或缺的条件之一.

一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(十一)AI系统

谈到人工智能(AI),这个话题就太大了:大学里有<人工智能教程>专门讲这方面的知识,什么大名鼎鼎的人工神经网络.遗传算法等等均可一窥究竟,这里如赘述似乎有些班门弄斧,我们暂且丢它一边去吧. 本节,我的主要目的是与大家共同探讨AI在RPG游戏中的应用.看过之前教程的朋友一定不会陌生,A*算法就是其中的一个重要组成部分:而本系列Demo中则使用了更为高级的改进型A*算法,不仅优化了性能,同时也大幅提升了玩家的操控体验.除此之外,AI更常见于RPG游戏中的角色,接下来我将引领大家循着AI的足迹,逐步

一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(一)序言

不得不说的事,过年期间用了两个多星期时间将17173首页所推荐的2010年新测的几乎60多款网游彻底的扫荡了一遍:过瘾哪!确实过瘾,好久没玩网游了,一次让我爽个够.快的2小时就到了40级,还有更快的5小时冲到了80级.感慨啊真想长叹一声:天!现在的游戏咋被整成了这样!于是愤愤写下如此感受,仅当到此一游:国产3D网游质量恒古不变,敢问开发商你自己想吐了没?市场上充斥着更多的依旧是2D/2.5D ARPG,换汤不换药,十个开发商有九个都在估量着换个美工班即得款新网游,那招个美工连岂不得登上年度大作?

一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(十二)魔法系统

世界首款Silverlight – MMORPG:<<窝窝世界>>震撼登场!伴着与XNA合体后的Silverlight 5 强势发布,一波Silverlight网游研发海啸即将席卷全球!  多磨的好事依旧让人激动,于是一不小心写下10款全新的魔法效果旨在祝贺.今天的教程不会让你失望,没错,又是一场超豪华魔法盛宴!接下来您将看到的是本教程ARPG Demo战斗实景,一切灵感与临摹均来源于近期即将内测的2.5D大作<倩女幽魂Online>(以下左边为倩女幽魂实景,右边为De

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

或许大家依旧对上一节中的"黑夜"及"梦回过去"记忆犹新,追问下去HLSL到底是何方神圣能实现如此炫酷之效果?HLSL(高级着色器语言)作为微软的独门兵器,仅供Direct3D使用.Silverlight无比幸运,从第二个版本开始便已获得了这把旷世利器,虽然目前仅能发挥其不到3层之功力,不过前辈Moonlight近期已向世界宣布全面突破技术壁垒,HLSL的威力提升至7层左右.我们完全可以预料的是,未来Silverlight将手握HLSL,踏着GPU 3D API飞扬驰

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

Silverlight中的HLSL不仅适用于场景与动画渲染,对于游戏中的角色,我们同样可以利用它制作动画特写.较常见的比如角色传送时的淡入淡出.扭曲变形.幻化呈现等切换动画,当然还有例如角色被DeBuff时所表现出来的放大缩小以及虚弱时的不规则体形等.适当的场合为角色增加动画特写使得游戏更显精致而华丽,当玩家身心愉快的融入其中而流连忘返时,或许正是这些魔幻般的特效在背后默默的飘散着令人迷醉的芳香. 还记得Shazzam吗?要制作特写依旧离不开这款强大的工具,以角色的传送特写"幻降"为例