一個建立完整遊戲AI的案例:第一部分(作者:Geoff Howland)

來源:互聯網
上載者:User

人工智慧(AI)一直是一種背景開發技術,可是在未來的遊戲中對於AI的開發比重會不斷增加。如果你的遊戲的AI是跟不上水準,玩家對你的遊戲的評價會是過時的你會因此而感到不舒服。
遊戲AI不僅僅是神經網路和學習系統,以及複雜的數學演算法。雖然可以使用這些,但遊戲的AI主要是建立一種環境和外在的表現通過遊戲中的對象體現出來。遊戲AI要有行為性,而不是科學性。
一個建立遊戲AI的關鍵是要明確遊戲最終表現的結果是什麼。這將全部展現在遊戲玩家眼前。如果這無法表達出來,那最好還是別說了。
以下的一個例子和探討是關於即時戰略遊戲的,其中很多的概念可以應用於其它類型的遊戲。所有的代碼是用C語言:

狀態機器和有限狀態機器:
一個有限狀態機器(FSM)是一個系統,其中包含一定數量的操作狀態。一個真實世界裡一個開關會有開和關兩種狀態,或一個鬧鐘會到時響起。有響起,記時和定時三種狀態。任何系統其中如果包含有限的可以被定義成一種狀態的能力,則可以將其定義為一種有限狀態機器。
有限狀態機器在許多程式中應用,並且明白如何有效建立遊戲AI是和建立一個遊戲世界一樣困難,所以要儘可能的詳細和簡明扼要。
如何使用有限狀態機器
在遊戲中使用FSM有許多目的,但其中一個比較難處理的是如何規範一個行為模型來類比人類的行為,這是相當困難的。想類比人類的行為經常會出錯,已經有很多的遊戲中出現這種情況這些都被遊戲玩家們發現並指出來了。而且還是在非常詳細的FSM系統下。
當你設計一些非常精確的關於人類學習和思考的系統時,你可以用一種簡單的方式判定,想象作為一個人,你會怎樣做出選擇。當學習了更多關於AI的決定和學習系統後,仍然要用這種方法,這樣往往會很簡單的設計出來而不是那樣的具有科學上地精確性。
不要因此產生誤解和對神經網路系統,遺傳演算法以及其它人工智慧演算法的抵觸,,只是要選擇一些明智的解決途徑和有趣的演算法,作為更好的解決方案,並且達到最佳效果。用你要達到的最終目的來衡量,並作出選擇,並且不要認為是唯一的。

遊戲狀態機器:
建立一個滿意的遊戲環境,意味著要盡量考慮許多玩家可能注意到的詳細的環節。更多情況下要預先計劃並測試,這樣當玩家在遊戲環境中不斷移動時會沉浸於其中。
在你的所有的遊戲狀態中,至少要有兩個狀態機器,以便遊戲順利進行。第一個狀態機器是處理遊戲介面的,包含遊戲是否暫停,玩家遊覽世界的模式如果有很多種,可以列出來,有些玩家可以或不可以看到的,以及其它一些標記可以做成特殊的介面。
struct GameLevelState {
  int alert;            // Alert status of enemies //
  struct Positionshot;  // Position of last shot fired //
  int shotTime;         // Game cycle last shot was fired //
  int hostage;          // Hostage rescued //
  int explosives;       // Explosives set or not //
  int tank;             // Tank destroyed //
  int dialogue;         // Dialogue variable //
  int complete;         // Mission completed //
 };

靈活性:
保持遊戲AI的靈活性是非常重要的。如果你把規則定的很標準,你將更加容易將其進一步擴充。理解設計一個遊戲AI是和設計一種內部線程是很相似的,你需要嘗試在此之上建立它們。
建立一個好的AI的目標是看起來所有的遊戲單位都是在環境中彼此之間相互影響的進行一些行為。沒有這些,對遊戲對象的適應是很難的而且遊戲的介面也會很糟。如果玩家沒有控制遊戲單位的感覺和獲得遊戲單位的返回資訊,則玩家只會在一個遊戲介面中毫無目的的點來點去,所有對該遊戲的沉浸感將無影無蹤。這意味著玩家將對此感到毫無樂趣和厭倦。
下面是一個你可能會提供給玩家的遊戲資訊的一個結構:
struct Character {
  struct Positionpos;               // Map position //
  int screenX, screenY;             // Screen position //
  int animDir, animAction, animNum; // Animation information, action and animation frame number //
  int rank;                         // Rank //
  int health;                       // Health //
  int num;                          // Number of unit //
  int group;                        // Group number //
  int style;                        // Style of unit (elf, human) //
  struct AnimationObject animObj;   // Animation object for complex animations //
};

以下是一些變數的定義:
pos變數定義了遊戲單位的位置座標,screenX, screenY是為了在螢幕上顯示遊戲單位的一些相關資訊如健康值和是否被選擇。
animDir, animAction 和 animNum都是用來定義遊戲單位的動畫狀態,這些都會在螢幕上顯示。
rank 和 health變數是遊戲單位的屬性資訊。
num變數是遊戲單位在遊戲單位元組中的序號。當調用遊戲單位的相關資訊時,用來選擇相應的遊戲單位,不需要直接給出結構的地址。
group變數決定遊戲單位屬於哪個編組,作為一個遊戲單位會屬於一個編組中。只有當單位死亡後才不會屬於一個組中。
style 和 animObj是更多的遊戲單位顯示資訊。
建立更進階的部分:
當你的遊戲單位按照一定的路線進行時,更進一步,是時候建立更多資訊使它們好象在過真正的生活。
你需要思考是什麼讓遊戲單位不斷重複的去做某件事。你想讓他們有情感嗎?你想讓他們恐懼,奔跑,想一個婦女一樣購物嗎?
你需要繼續添加變數來決定情感狀態。最好的理解遊戲單位的情感成分是,先在自己身上做一些設想。為了建立一種人類的反映機制,你需要瞭解一個真實的人是怎樣做反映的。
在另一方面,幾乎是相對於人類的情感,這裡提供了一個符合的經驗並不基於現實,但可以用於挑戰玩家。除了使遊戲單位擁有人類天性,你還需要想想,是否有理智讓你的遊戲單位去做這些反映。問題是你必須做出結論,是否要添加這些,或是只是簡單的結束,用單調的反映機制,雖然做起來很容易,或只用隨機的方式解決。所有這些可能毀了一個好遊戲,所以要多做些功能進去,但有一點很重要,就是要讓玩家玩一輩子也不知道是怎麼弄出來的!

建立組:
建立組還是不建立?
如果你做了一個第一人稱射擊遊戲,當然用不到。可是,在即時戰略遊戲中或一個玩家控制不止一個遊戲單位的遊戲中,有個問題要知道:
你需要你的單位在一種協和的方式中行動嗎?
如果你回答是,這裡有個好主義,即建立組。如果回答不,則好處是你不必將資訊傳給組裡的每個遊戲單位,尤其是在一個目標點改變時。
多個遊戲單位的協同行動,比如巡邏建築,可以控制在一個中央目標點附近。而不必讓每個遊戲單位獨自行動,並檢測是否碰到其他的遊戲單位然後在返回從新確定位置。
組可以保持它們的共同結構,所以發布一個指令只需要花費向一個遊戲單位發布指令一樣的時間。更重要的是你將建立一些容易理解和讀取的方式。操控25個遊戲單位並讓其相互連信變的非常簡便。
建立在組上的行動,對於障礙迴避和檢測變的容易,並且尋找路徑的時間也減少許多,這在有大批的遊戲單位的狀態下是很有效。
大場面:
組織好你的組,就想建立遊戲AI一樣,想象調動所有的遊戲單位做最後的進攻。這裡有個想法是建立一塊地區作為監控中心,以便遊戲單位可以快速的被發現。想法是不複製任何資料,你只需在一個資源中尋找資料,這個地區將建立在最合理的位置,其他邏輯擴充的功能也應該在合理的位置。
根據我地經驗,我決定這樣做區分,任何必須和遊戲單位有關聯的將作為一種附加物放到遊戲對象資料結構中。
這意味著遊戲對象在行動的過程中,或在他們所在的物理座標上做某些行為時,一直不會有任何資訊處理,比如動畫序列和全局座標。這樣做意味著一個遊戲單位必須屬於一個組才有能力移動或改變行為。如果他們是獨立的,則整體做為一個組對待。
大批單位中的一個單位:
我們最終找到一個組,以便進行統一的行動,一個座標系統是建立很多小塊,這尤其在遊戲單位尋路時很重要,所以當我們需要組結束編隊,並單獨行動,需要建立如下結構:
struct GroupUnit {
  int unitNum;                  // Character Number //
  struct Unit *unit;            // Unit character data //
  struct Positionwaypoint[50];  // Path in waypoints for units //
  int action[50];               // Actions by waypoints //
  int stepX, stepY;             // Step for individual units, when in cover mode //
  int run, walk, sneak, fire, hurt, sprint, crawl;          // Actions //
  int target;                   // Targets for units //
  struct Position targetPos;    // Target Position //
};

變數含義:
unitNum是組中遊戲單位的數量。如果組中最多有10個單位,這裡將有10個位置。
unit是一個指標,指響unit結構,將儲存遊戲單位當前的座標,健康值和其他資訊。一個遊戲單位的生命值標記將指示該遊戲單位是否受傷或正在和其他遊戲單位進行溝通,或其它一些資訊。
waypoint數組是遊戲單位移動的路徑序列。所有行動和waypoints是唯一指定在GroupUnit結構裡的,取決於組是否編隊。
action數組包含了移動後的行為。允許建立更多的指令序列,控制遊戲單位隱秘行動或迅速移動,你還可以想象其他的戰略性的行為。
stepX, stepY是一個速度資訊;每禎的移動所有的遊戲對象。恰當使用可以適合所有物理性的事件發生時。在一個普通的系統下通常減少處理時間。
run, walk, sneak是處理不同的遊戲單位狀態。並不是動畫,但是動作狀態可以做標記,還有很多狀態,可以互相影響。
target,targetPos用來指定攻擊目標,和自身位置座標。敵人的座標,和健康值和其它屬性一樣,可以用敵人的遊戲單位號來尋找,但為了方便讀取我決定保留一個本地的敵人座標的拷貝。
群體智能:
我們的最終目的是要有一個中心位置為盡量多的資料儘可能限制單位元和線程數並使問題簡單話。來看以下的資料結構:
struct Group {
  int numUnits;              // Units in group //
  struct GroupUnit unit[4];  // Unit info //
  int formation;             // Formation information for units and group //
  struct Position destPos;   // Destination (for dest. circle) //
  int destPX, destPY;        // Destination Screen Coords //
  struct Position wayX[50];  // Path in waypoints for group //
  float formStepX, formStepY;  // Formation step values for group movements //
  int formed;                // If true, then find cover and act as individuals, otherwise move in formation //
  int action, plan;          // Group action and plans //
  int run, walk, sneak, sprint, crawl, sniper;   // Actions //
  struct Position spotPos;   // Sniper Coords //
  int strategyMode;          // Group strategy mode //
  int orders[5];             // Orders for group //
  int goals[5];              // Goals for group //
  int leader;                // Leader of the group //
  struct SentryInfo sentry;  // Sentry List //
  struct AIStateaiState;     // AI State //
};

numUnits提交組裡遊戲單位的數量,遊戲單位元組儲存GroupUnit資訊。這個特殊的組只允許有最大4個遊戲單位元
formation是一個是否編隊的標記,決定編隊的類型。可以編隊成柱形,楔形,菱形。只需定義相應的編號。
destPos 和 destPX,destPY是提供到達目的地的資訊迅速對玩家的操作做出反映。waypoints和steps是獨立單位的控制方式,在編隊中的所有遊戲單位都將有相同的速度,這樣才可以保持對型。不需要為每個單位改變速度。
formed是決定是否遊戲單位存在編隊或單獨行動。如果有對型則所有遊戲對象將進行同樣的操作。如果有原因不能用一種方式移動,比如遭到進攻或必要的資訊中斷,遇到障礙,遊戲單位就各自移動。
actions是獨立的行為指定,比如如果有個狙擊手在組中,你不可能讓他統一行動。這就是將遊戲單位區分的邏輯組,並控制狙擊手在組的層級下行動。這種設計就是在最佳設計結構思想下做出的。
strategyMode是一個靈活變數決定怎樣對敵人做出反應。是勇敢的,有謀略的,還是防禦性的,還有投降?用一種簡單的存取形式用來控制基本的響應,是一種好方法減去許多獨立遊戲單位和組的狀態計算。更好的提供玩家控制,玩家可以設定不同組來做不同的行動。
orders 和 goals數組指明命令和目的,在命令和目的資料庫中規定的行為要求多個組方便的作出行為反映。
sentry 和 aiState包含是否站崗和響應的AI狀態值
合在一起:
現在已經有了一些組的結構,下面介紹如何使用:

一定要仔細的編寫AI程式,要規範和靈活,這樣才可以隨意添加,方便調用每部分。思路是要有資料的組織架構,在一個函數裡做一些有特殊性的功能。然後在其他地方調用。最後如果你的AI有問題,需要調試。則不需要檢查每條語句,因為有一個特殊的函數,至少要有這種習慣。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.