还记得当年的经典网游奇迹(MU)吗?辉煌就如同其名字一般深刻烙印在我的脑海。与朋友们一起通宵奋战的日子已成过去,残留世上那一张张经典不朽的截图让我时刻感受回味。它的成功不仅仅因为其拥有一个极棒的世界观,更深层的却是那些超酷且绚丽的魔法效果,曾经打动着无数年轻的心。
本节我将以奇迹中So cool的“激光”魔法为蓝本,向大家展示如何制作矢量魔法:
不知道这张图是否能打捞起大家沉淀的回忆,此乃奇迹当年与地狱火并列的两大魔法之一:激光,画面漂亮且更重要的是它具有直线穿透群攻效果。要模仿它我们可以先通过PS制作一张模拟草图,从中了解该魔法画面的颜色及渐变规律,这将为我们后面在WPF/Silverlight中构造它提供参考:
通过PS中的渐变工具再配合外发光效果,我们可以轻松的制作出上面的草图,接下来回想一下前面所讲过的内容不难分析出在WPF中我们可以通过绘制一个圆角矩形并配上彩虹画刷,最后为此矩形添加位图外发光特效即可实现以上效果。有了原理,用xaml语言来描述它就再简单不过了。我们首先在项目中添加一个名叫QXLaser的用户控件,然后设置其xaml界面容器代码如下:
……
<Canvas>
<Rectangle x:Name="Body" Width="700" Height="80" RadiusX="80" RadiusY="80">
<Rectangle.RenderTransform>
<RotateTransform x:Name="Rotate" />
</Rectangle.RenderTransform>
<Rectangle.BitmapEffect>
<OuterGlowBitmapEffect x:Name="Outer" GlowSize="40" Noise="0" Opacity="1" />
</Rectangle.BitmapEffect>
</Rectangle>
</Canvas>
……
其中RadiusX与RadiusY分别定义激光魔法的圆角,并通过BitmapEffect中的OuterGlowBitmapEffect为激光魔法添加外发光效果(此特效很不错,可是会占用大量的界面线程资源,本文只是为了达到目的而借用之,画面会卡就是因为它的存在。我曾在第二十五节中有提到过相关知识;值得庆幸的是,在Silverlight中此类特效效果及性能均表现优良,有兴趣的朋友不妨在Silverlight中测试体验一下),此时大家是否有注意到,我还为该激光魔法添加了一个RotateTransform,因为它与上一节中的群攻魔法有一定的区别,它是具有方向的,因此我们需要通过旋转变换来实现相关需求。这里我为其旋转对象取了个名字Rotate以方便后台代码能对其进行操作。
界面绘制好后,我们还需要为控件添加一些属性,这些属性与上一节中的魔法控件的属性基本相同;需要特别指出的是Fill与OuterFill这两个属性,它们分别用来设置激光魔法内部的填充及外发光颜色。
接下来还需要在Config.xml文件中为激光魔法设定参数:
<Magic Type="1" Code="6" FrameNum="20" EffectiveFrame="0">
……
</Magic>
这里我新加了一个参数叫Type,用它来区分不同类型的魔法,因为不同类型的魔法它的范围、方向、伤害处理等均存在非常大的差异,我们必须分类进行处理。
最后,我们通过仿造类似上一节的魔法处理代码,即可将激光魔法运行起来。但是又出现了新的问题:由于激光属于矩形直线穿梭类型魔法,在伤害计算上会有些特殊,该如何进行相关的设定呢?大家不妨先看下图:
当我们点击B点时,激光魔法将从主角的手位置点A发出,接着我们通过计算获得B与A之间的角度,并对激光魔法按此角度进行旋转,最后得到触发伤害的范围即为上图中粉色点阵所包围的区域;在已知点A与点B的坐标,以及激光魔法的长度,我们可以很简单的计算出激光魔法伤害范围其不规则矩形的4个顶点坐标,从而我们可以通过System.Drawing命名空间中的相应方法来循环判断地图中的精灵是否在该不规则矩形内来对其进行伤害处理:
/// <summary>
/// 判断点是否在多边形内
/// </summary>
/// <param name="range">多边形顶点范围</param>
/// <param name="target">要判断的点</param>
public static bool PointInPolygon(System.Drawing.Point[] range, System.Drawing.Point target) {
System.Drawing.Drawing2D.GraphicsPath myGraphicsPath = new System.Drawing.Drawing2D.GraphicsPath();
System.Drawing.Region myRegion = new System.Drawing.Region();
myGraphicsPath.Reset();
myGraphicsPath.AddPolygon(range);
myRegion.MakeEmpty();
myRegion.Union(myGraphicsPath);
return myRegion.IsVisible(target);
}
与上一节中魔法的伤害范围以鼠标点击的点为圆心的圆类似,此方法可以拓展到任意个点的多边形,无论是闭合的或是不闭合的。毫不夸张的说,所有范围攻击类型魔法均可以采用此方法来判断,本节的精华哦! ^ ^
至此我们完成了激光魔法的整个制作及使用流程。回过头来,大家有没有想过为什么我们要使用矢量图形魔法?因为矢量魔法控件可以根据参数的不同自由的更改例如颜色,尺寸,旋转等等,就好比本文的激光魔法,我们只需修改Fill和OuterFill这两个属性即可让整个激光改头换面:
//深蓝激光
laser.Fill = Super.CreateRainbowBrush(231, 255, 255, 0, 255, 255, 255, 0.5, 231, 255, 255, 1);
laser.OuterFill = Colors.MidnightBlue;
又如:
//红色激光
laser.Fill = Super.CreateRainbowBrush(255, 225, 225, 0, 255, 255, 255, 0.5, 255, 225, 225, 1);
laser.OuterFill = Colors.Pink;
是不是很神奇!更甚者,我们还可以根据需要,让激光从产生后逐渐变长直到最后消失:
矢量魔法的灵活万变告诉我们,只要您拥有一流的矢量绘图能力,均可以制作出强大且性能优越的矢量控件,这是使用WPF/Silverlight开发高性能高质量游戏所必须的,同时也是位图控件所不能比拟与替代的。
本节的源码中我还添加了几个新的魔法,大家在运行的时候是否发现它们的名称后面均带有一个属性名,如“激光[雷]”。其中“雷”代表该魔法具有雷属性;在以往的游戏中,雷属性意味着麻痹,这就是我下一节将为大家讲解的如何在游戏中实现魔法的不同属性效果,敬请关注。
出处:http://alamiye010.cnblogs.com
教程目录及源码下载:点击进入(欢迎加入WPF/Silverlight小组 WPF/Silverlight博客团队)
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。