C#開發WPF/Silverlight動畫及游戲系列教程(Game Course):(三十一) 超酷萬變的矢量魔法
還記得當年的經典網游奇跡(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