基礎 | 簡單的智能體----有限狀態(tài)機(六)

本系列為筆者初學c/c++和游戲AI開發(fā)的學習經(jīng)歷,練習為主,不涉及到具體的游戲開發(fā)軟件學習(如unity,虛幻4等),適合剛入門的小伙伴一起學習探討,歡迎在評論區(qū)留下意見。
?開發(fā)語言:c/c++ (11及以上)?
開發(fā)平臺:macOS mojave / Linux?
編譯器:vs Code / g++

三、代碼實現(xiàn)
3.3 礦工Bob
??在3.2里我們定義了一個居民類,表示小鎮(zhèn)上的居民都具有的一些共同特征。之后,我們又將構建一個“礦工類”,這個類描述了“礦工”的屬性、狀態(tài)和行為,是一個真正意義上的智能體。
? Bob會渴,會餓,會走來走去,會睡覺,會挖礦。這些都是有別于其他居民的特征和行為,也是他作為一個游戲智能體的存在條件。雖然比較簡單。
? 這里,我們需要用到c++的特性之一,繼承。
? 類繼承能夠從已有的類派生出新的類,而派生類繼承了原有類(稱為基類)的特征,包括方法。
----《C++ Primer Plus》
? 繼承的目的之一,就是為了提高代碼的重用性。這樣,不管我們創(chuàng)建多少個“礦工Bob”,都可以只用同一套代碼來表示他們的共性。而不用每個人都寫一遍。
3.3.1?Miner類實現(xiàn)

? 可見,Miner類公開繼承了BaseGameEntity類,也就是說每個Miner類都會有一個ID和Update()函數(shù),由于Update()函數(shù)是純虛函數(shù),因此它不用在基類中實現(xiàn),但是一定要在派生類中被覆蓋且實現(xiàn)。
? 方框里是Miner類的一些行為函數(shù),當Bob處在某個狀態(tài)中時,他的一些屬性會發(fā)生變化,這些改變通過方框里的函數(shù)來實現(xiàn)。?
? 其中某些函數(shù)用到了關鍵字const,用來定義一個不會被改變的常量,可修飾 普通變量、指針、函數(shù)參數(shù)和類的成員函數(shù)。
? const 修飾類成員函數(shù),其目的是防止成員函數(shù)修改被調(diào)用對象的值。

? 圖11是Miner類的初始化,除了必須有的id之外,注意我們一開始也是要給Miner類一個初始狀態(tài)GoHomeAndSleepTilRestted::Instance()?,這個類就是接下來要講的具體狀態(tài)類。
? 目前,一個礦工只有四種狀態(tài),也即一個Miner類有四個具體狀態(tài)類。
? 其中,我們重點了解一下Update()和ChangeState()的實現(xiàn):
Update()函數(shù)被用來更新Bob的狀態(tài),每個時刻執(zhí)行一次,每次執(zhí)行的時候饑渴值+1,同時執(zhí)行當前狀態(tài)的Excute()函數(shù)。之所以這樣做,是因為我們用狀態(tài)模式,將具體狀態(tài)類從Miner類中分離了出去,并用單例模式來實現(xiàn),因此Miner類只能通過Update()來更新狀態(tài)。

ChangeState()函數(shù)被用來改變Bob的狀態(tài),只有當滿足某種條件之后才會執(zhí)行。我們規(guī)定每次改變狀態(tài)的時候,都要先用Exit()來退出當前的狀態(tài),再通過Enter()來進入新的狀態(tài)。

? 最后一點,我們額外定義了一個枚舉類型來存儲Bob的位置,方便記憶和操作:


知識點:
類的實現(xiàn) & 類的初始化方式
繼承
const關鍵字的用法
枚舉類型

參考:?
《游戲人工智能編程案例精粹》
《C++ Primer Plus》?
相關代碼下載:https://github.com/linpeijie/GameToy/tree/master/GameAI/FSM