C#開發WPF/Silverlight動畫及游戲系列教程(Game Course):(二十九) 人工智能(AI)之追蹤者
經過前面28節的不斷完善,主角已經具備了MMORPG游戲中的大多數功能;但是其他精靈例如怪物等暫時還是無法行動的,上一節中它們無辜的充當了主角的肉靶子,它們開始吶喊:上帝呀,請給予我們靈魂與智慧吧!其實靈魂早就有了,就是精靈的生命線程。那麼該如何賦予精靈智慧呢?
精靈智慧的實現其實就是為精靈賦予AI(人工智能)。完整的游戲引擎或多或少都必須擁有一定的AI,例如棋牌類型游戲有著它們獨特出牌AI,射擊類型游戲同樣也擁有相應的計算AI等等。AI的類型在不同類型游戲中有著不同的體現與定位,可深可淺,甚至無限擴充的可能。在MMORPG類型的游戲中則以“追蹤者”為最基礎的精靈用AI,同時也是游戲中使用率高達80%以上的AI類型。何謂“追蹤者”?簡單的說就是當怪物發現敵對玩家或是其他敵對精靈時即會鎖定目標並向其位置移動,一旦對方進入自己的攻擊范圍後即刻發起物理或魔法攻擊;同時,如果對方跑開,自己會繼續追擊且循環重復前面過程,就好比一個幽靈纏著你。這段描述大家是否有種四曾相似的感覺?沒錯,“追蹤者”AI其實就是上一節中主角戰斗功能模塊實現的最直接體現。下面我將為大家講解如何通過代碼實現怪物的“追蹤者”人工智能。
游戲AI設計同樣是對游戲引擎框架合理性的重要考驗,大家回想一下,主角與怪物均為QXSpirit類型控件,通過前面的章節我們已經實現了主角大多數的功能,如移動、攻擊、追擊、傷害等等;同樣的,我們是否可以將用於實現這些功能的方法為其他所有精靈通用?這是肯定的。比如障礙物預測使用的方法WillCollide(),直線移動方法StraightMoveTo(),尋路移動方法AstarMoveTo(),判斷移動到達目的地方法ArriveTarget()等等,這些方法在前面章節中均是無參數的,裡面的處理均以Leader為主元素進行相應的屬性設置及修改。此時我們不妨為這些方法均添加一個QXSpirit spirit參數,然後將方法裡的Leader全部改成spirit;如此,在除法AI後,所有的精靈對象就都可以重用這些方法了:
舉個例子,好比原先的ArriveTarget()方法寫法如下:
private bool ArriveTarget() {
return (storyboard != null && storyboard.GetCurrentProgress(Leader) == 1) ? true : false;
}
改成AI通用的則為:
private bool ArriveTarget(QXSpirit spirit) {
return (Super.storyboard.ContainsKey(spirit.Name) && SpiritStoryBoard(spirit.Name).GetCurrentProgress(spirit) == 1) ? true : false;
}
不光是多了個參數,同時大家是否有注意到我將storyboard定義成了一個字典以存放所有精靈的移動動畫板:
public static Dictionary<string, Storyboard> storyboard = new Dictionary<string, Storyboard>();
每個精靈在移動的時候會首先判斷以自身名字(spirit.Name)為鍵名的Storyboard鍵值是否存在,如果不存在則創建一個新的,接著在此Storyboard上執行移動屬性動畫,例如直線移動方法改為:
private void StraightMoveTo(QXSpirit spirit, Point p) {
……
if (!Super.storyboard.ContainsKey(spirit.Name)) { Super.storyboard.Add(spirit.Name, new Storyboard()); }
……
}
使用字典來管理所有精靈的移動動畫板即方便又高效,我們只需要通過Lambda即可以輕松獲取指定鍵名的Storyboard:
private Storyboard SpiritStoryBoard(string key) {
return Super.storyboard.Single(X => X.Key == key).Value;
}
同樣的也可以在每次移動時這樣創建新的Storyboard:
private void NewSpiritStoryboard(string key) {
if (!Super.storyboard.ContainsKey(key)) {
Super.storyboard.Add(key, new Storyboard());
}
}