快捷搜索:

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对目标设置设备摆设部件首先辈行复制,然后按照如上要领随机抽取部分设置设备摆设实体上的粒子进行发射飘散:

显示风中粒子

///

/// 显示风中粒子

///

///

所修饰角色

///

所参照的设置设备摆设

///

粒子类型

///

颜色

///

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; iamount; 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

您可能还会对下面的文章感兴趣: