C#開發WPF/Silverlight動畫及游戲系列教程(Game Course):(三十二) 雷、混、冰、毒、火、風 - 幻化中的魔法魅力
本節,我將為大家演示如何為游戲中的魔法增加華麗的附加屬性。
第一步,定義規則:
1)定義魔法附加屬性分類:在本教程示例游戲中,我將魔法附加屬性定義為6類:雷、混、冰、毒、火、風,為什麼要以這樣無規律的方式去命名?因為是教程,我們需要學習的是如何實現對應效果,此6類屬性算是目前網游中最流行的六大魔法屬性,如果大家都掌握了,無論是中國式5行還是諸如其他的風格設計,均能做到游刃有余。
2)定義魔法附加屬性功能及效果:
雷 – 麻痺 – 精靈麻痺(被附加該屬性精靈將無法動彈)
混 – 混亂 – 精靈混亂(被附加該屬性精靈將亂跑)
冰 – 冰凍 – 精靈減速(被附加該屬性精靈移動速度、物理攻擊速度、施法速度均減慢)
毒 – 中毒 – 精靈中毒(被附加該屬性精靈每秒持續減生命值)
火 – 燃燒 – 精靈灼傷(被附加該屬性精靈所有防御類屬性值降低)
風 – 虛弱 – 精靈弱化(被附加該屬性精靈所有攻擊類屬性值降低)
對應枚舉:
<ExtraItems>
<Item Value="0" Src="Interface/Icon/Extra0.png" Name="麻痺" Description="效果:無法動彈" />
<Item Value="1" Src="Interface/Icon/Extra1.png" Name="混亂" Description="效果:亂跑" />
<Item Value="2" Src="Interface/Icon/Extra2.png" Name="冰凍" Description="效果:速度減緩" />
<Item Value="3" Src="Interface/Icon/Extra3.png" Name="中毒" Description="效果:持續傷血" />
<Item Value="4" Src="Interface/Icon/Extra4.png" Name="燃燒" Description="效果:所有防御屬性值降低" />
<Item Value="5" Src="Interface/Icon/Extra5.png" Name="虛弱" Description="效果:所有攻擊屬性值降低" />
</ExtraItems>
3)定義魔法附加屬性視覺表現:
麻痺 – 雪白
混亂 – 黃色
冰凍 – 天藍
中毒 – 綠色
燃燒 – 紅色
虛弱 – 灰色
第二步,具體實現:
首先我們需要考慮的是如何實現精靈的變色,即如何改變精靈圖片源的色相。在很多編程語言中都有現成的類庫可以調用,但是在目前的 WPF/Silverlight中,至今我未能找到一種直接改變圖片色相的方法。但這並不意味著WPF/Silverlight就此束手無策了,WPF /Silverlight的強大圖形表現能力讓我想到了控件蒙版,既然直接的不行,那麼我們就來間接的。
接下來我們為精靈控件QXSpirit的表現層xaml中添加如下一個矩形蒙版:
<Rectangle Name="BodyMask" Opacity="0.3" Visibility="Collapsed" Panel.ZIndex="1">
<Rectangle.OpacityMask>
<ImageBrush x:Name="BodyMaskSource"></ImageBrush>
</Rectangle.OpacityMask>
</Rectangle>
此精靈身體蒙版默認情況下是不可見的,它的透明度為0.3,並且ZIndex必須覆蓋於精靈之上。只要我們在後台cs中將此蒙版寬高與精靈圖片源寬高時刻保持聯動一致,這樣,當需要的時候通過設置BodyMaskSource.ImageSource = Body.Source;然後根據前文中相應的視覺表現賦予蒙版Fill顏色,並將之顯示出來。即可以輕松的模仿實現精靈圖片源的色相改變。
實現色相改變原來如此的簡單,只是在性能上來說等於增加了多余的消耗,但這並不是長期的,僅僅當精靈被施與附加屬性後才會短時間變色,在恢復正常後即將蒙版隱藏,Collapsed將不再占用界面資源。
完成了界面,剩下的就是實現邏輯。魔法附加屬性不可能是永久的,就好比中毒有個中毒持續時間,麻痺有麻痺持續時間等等,除了那些即效魔法外,本文介紹的這6類魔法附加屬性均為持續性的。因此,我通過為精靈控件添加一個ExtraTime屬性來記錄精靈被施與魔法附加屬性的持續時間:
double[] _ExtraTime = new double[6];
/// <summary>
/// 獲取或設置被附加屬性對應持續時間,與枚舉ExtraAttributes一一對應
/// </summary>
public double[] ExtraTime {
get { return _ExtraTime; }
set { _ExtraTime = value; }
}
該時間數組為double類型,分別與枚舉ExtraAttributes一一對應。通過如此設置,我們可以輕松的借助主界面間隔為1秒的輔助線程 AuxiliaryThread去同步更新它們(每秒-1),並實現例如中毒每秒傷血等相關業務邏輯,可謂水到渠成,無縫銜接。
由於此6種附加屬性實現的相應功能相差較大,基本無統一的規律可尋,因此下面我將按類型分類進行講解:
1)雷:
本示例教程中我將之定義為使精靈無法動彈,無法動彈一方面意味著它自身動作被鎖定,另一方面表示它無法移動。代碼實現即:
if (enemy.VLife > injure) {
enemy.BodyMaskColor = new SolidColorBrush(Colors.Snow);
enemy.BodyMaskSource.ImageSource = enemy.Body.Source;
enemy.TimerState = TimerStates.Stop;
Super.PauseSpiritStoryboard(enemy);
} else {
enemy.TimerState = TimerStates.Start;
}
同時需要為直線移動方法與A*移動方法開頭添加一個判斷: if (spirit.ExtraTime[0] > 0) { return; }
測試效果截圖:
2)混
本示例教程中我將之定義為使精靈隨機亂向跑動。此附加屬性非常有趣,實現起來也很簡單,我們只需將精靈的移動目標進行重新隨機更改,即為直線移動方法與A*移動方法開頭添加如下一個判斷處理即可:
if (spirit.ExtraTime[1] > 0) {
p = new Point(p.X + (p.X > spirit.X ? -random.Next(200) : random.Next(200)),
p.Y + (p.Y > spirit.Y ? -random.Next(200) : random.Next(200)));
}
測試效果截圖:
3)冰:
本示例教程中我將之定義為使精靈移動速度、攻擊速度、施法速度減速。大家回憶一下第二十八節中關於精靈屬性的設計,其中精靈的所有類型屬性均由4個部分組成,以下為這3個速度屬性的構造定義:
/// <summary>
/// 獲取跑步速度(每移動一個單元格的花費時間,越小越快)
/// </summary>
public double VRunSpeed {
get { return ABase[5] + Equip[5] + Buff[5] - VAgile * Coefficient[5]; }
}
/// <summary>
/// 獲取物攻速度(越小越快)
/// </summary>
public double VAttackSpeed {
get { return ABase[6] + Equip[6] + Buff[6] - VAgile * Coefficient[6]; }
}
/// <summary>
/// 獲取施法速度(越小越快)
/// </summary>
public double VMagicSpeed {
get { return ABase[7] + Equip[7] + Buff[7] - VAgile * Coefficient[7]; }
}
其中的Buff即為附加屬性影響的部分。了解了原理,將之轉換成機器語言即為:
enemy.Buff[5] = enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[6] = enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[7] = enemy.ExtraEffect[magic.ExtraAttribute];
當判斷冰凍持續時間減為0後,我們只需更新這3個Buff值歸0即可。是不是很方便?嘿嘿,同時也證明了第二十八節我對精靈屬性結構設計定義的正確性。
測試效果截圖:
4)毒:
本示例教程中我將之定義為精靈每秒持續傷血。此效果實現起來更簡單了,只需要在主界面間隔為1秒的輔助線程計時器中對中毒時間是否大於0進行判斷,然後進行相應的傷害處理即可;並且其他的所有附加屬性的時間減少均寫在該方法內:
//同步激發精靈附加屬性效果
for (int i = 0; i < Carrier.Children.Count; i++) {
if (Carrier.Children[i] is QXSpirit) {
QXSpirit spirit = Carrier.Children[i] as QXSpirit;
if (spirit.VLife != 0) {
for (int j = 0; j < spirit.ExtraTime.Count(); j++) {
if (spirit.ExtraTime[j] > 0) {
//中毒則每秒傷血
if (j == 3) {
Super.DoInjure(Find(spirit.ExtraSpirit), spirit, spirit.ExtraEffect[j]);
}
//持續時間減少
spirit.ExtraTime[j] = spirit.ExtraTime[j] - AuxiliaryThread.Interval.Seconds;
if (spirit.ExtraTime[j] <= 0) {
//移除附加屬性效果
Super.RemoveExtraEffect(spirit, j);
}
}
}
}
}
}
測試效果截圖:
5)火:
本示例教程中我將之定義為降低精靈所有防御類屬性值。類似於冰的效果,處理時只需將物理防御力的Buff[9]、隔擋率的Buff[10]、魔法防御力的Buff[12]減少對應的火攻擊值即可:
enemy.Buff[9] = -enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[10] = -enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[12] = -enemy.ExtraEffect[magic.ExtraAttribute];
解除時3者歸0。
測試效果截圖:
6)風:
本示例教程中我將之定義為降低精靈所有攻擊類屬性值:
enemy.Buff[1] = -enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[2] = -enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[13] = -enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[14] = -enemy.ExtraEffect[magic.ExtraAttribute];
enemy.Buff[15] = -enemy.ExtraEffect[magic.ExtraAttribute];
解除時5者歸0。
該類型魔法影響對象精靈的最小物理攻擊的Buff[1]、最大物理攻擊的Buff[2]、最小魔法攻擊的Buff[13]、最大魔法攻擊的Buff[14]、暴擊率的Buff[15]等。
測試效果截圖:
非常酷的6大魔法附加屬性,基本上囊括了目前主流的魔法效果。好比麻痺,它又可以延伸出定身、眩暈、凍結等效果;冰凍同樣也可以分解成減慢移動速度、減慢攻速、增加魔法詠唱時間等等。
魔法世界的幻化莫測時刻讓我回味。教程至此已完美的诠釋了我曾經制作的WPF-ARPG游戲引擎,更有過之而無不及~後期的教程我將更深入的對目前的引擎進行補充、完善、優化!敬請關注。
出處:http://alamiye010.cnblogs.com/