實行較多狀態的角色,把動做全寫在一個部分中會致使維護成本高,拓展性低
例如:走路,跳躍,射擊,躲避的相互轉換,有些能夠轉換,有些不能,實現邏輯複雜
(滿屏幕都是if - else)併發
//包含着全部的狀態 enum class State{StateA, StateB, StateC, ...} activeState; ... //經過switch語句切換狀態,根據具體狀況實現細節 switch (activeState) { case State.StateA: ... break; case State.StateB: ... break; ....... } ...
狀態機的原形,用一個枚舉表示當前的狀態,經過填充完善switch語句實現狀態之間的切換,可是依然有維護成本高拓展低的缺點(雖然確實是比用if - else堆好)人工智能
最基本的狀態機,通常來講其餘狀態機都是這種狀態機的變體
對於狀態機的理解,最好就是畫個圖(如圖結構,方框是狀態,箭頭是狀態之間的聯繫)code
有限狀態機強調的是狀態之間的切換,以及對不一樣狀態的封裝,因此實現方法通常能夠根據需求調整
如下參考了《遊戲人工智能》的實現
首先須要個基類State和基類Translation對象
//狀態基類,全部狀態都繼承這個類 class State { public: virtual ~State(){} virtual OnStateEnter(){} //進入此狀態執行一次 virtual OnUpdate(){} //每一幀執行一次 virtual OnStateExit(){} //跳出狀態時調用一次 list<Translation> translations; //狀態遷移列表 }; //狀態遷移 class Translation { public: virtual ~Translation(){} virtual bool isValid() = 0; //用於斷定遷移,可切換返回true virtual State* getNextState() = 0; //進入下一個狀態 virtual void onTransition(){} //遷移時調用 };
State是每個狀態都會繼承的基類,translations中存着他指向其餘狀態的Translation,經過每一幀遍歷全部Translation的isValid()來斷定是否能夠跳轉,若能夠跳轉則執行自身的OnStateExit(),並將當前的狀態設置爲getNextState()得到的狀態blog
而後還有狀態機類,用來管理全部狀態:繼承
//狀態機類 class FiniteStateMachine { public: void Update(); //每一幀運行一次 State* initialState; //初始狀態 State* activeState; //正在運行的狀態 protected: list<State> states; //全部狀態的實例 }; void FiniteStateMachine::Update() { //遍歷活動狀態的全部遷移,如有可用的,則切換狀態 list<Translation>::iterator itr = activeState->translations.begin(); for (int i = 0; i < activeState->translations.size(); ++i, ++itr) { if (itr->isValid()) { activeState->OnStateExit(); //退出調用 activeState = itr->getNextState(); //切換活動狀態 itr->onTransition(); //切換調用 activeState->OnStateEnter(); //進入調用 return; //直接返回 } } //若是沒有狀態切換,運行一次update activeState->OnUpdate(); }
接下來具體的狀態細節就要具體繼承,具體實現遊戲
分層狀態機至關於對有限狀態機的進一步封裝,將複數個狀態封裝成一個大的狀態,再用一個「歷史狀態」記錄切出此狀態時運行的子狀態,就能夠在大狀態間切換(結構如圖)get
圖中將StateA和StateB加入到一個更高層的狀態StateD中,只需退出時記錄狀態,就能夠在CD狀態間切換,增長了狀態C的複用性(省略了AC,BC間的聯繫)
主要思想一是包裝更高的層次,二是高層的切換放到更高層來以爲以提升複用
分層狀態機的實現主要分兩種:
1、父狀態就是一個狀態機,能夠往裏面添加狀態
2、添加一個狀態棧儲存父子狀態,每個狀態都是棧下一個狀態的子狀態,進入狀態時入棧,結束狀態時出棧併發送一個消息,新棧頂狀態不能處理就再出棧,直到棧頂狀態能處理這個消息爲止。it
併發狀態機能夠理解爲一個對象擁有兩個同時運做的狀態機,兩個狀態機相互獨立(但能夠經過修改對象的狀態進行通訊),例如咱們能夠將腿部動做(站立,下蹲,奔跑)和手部動做(持槍,空手,瞄準)分離。io
下推狀態機的核心是他有一個狀態棧(但和層次狀態機實現的棧徹底不一樣,層次狀態機的棧是爲了記錄父狀態,這個棧是爲了紀錄上一個狀態)。
狀態棧主要解決的是狀態機沒法獲得上一輪執行的狀態。
實現時,在狀態機中加一個棧,在進入狀態時將狀態入棧,退出狀態時將狀態出棧,運行時則運行棧頂的狀態。
例如,我在作做業的時候餓了,想去吃東西。餓了去吃東西是多數狀態都能進入的狀態,而且結束「吃東西」的狀態後我要回復原來的狀態。
在運行時,狀態機已經將「作做業「入棧
而後「我餓了」,將「吃東西」入棧
「吃東西」結束,將「吃東西」出棧
繼續運行棧頂的「作做業」(事實上不可能)
如有錯誤,歡迎指出