基础 | 简单的智能体----有限状态机(六)

本系列为笔者初学c/c++和游戏AI开发的学习经历,练习为主,不涉及到具体的游戏开发软件学习(如unity,虚幻4等),适合刚入门的小伙伴一起学习探讨,欢迎在评论区留下意见。
开发语言:c/c++ (11及以上)
开发平台:macOS mojave / Linux
编译器:vs Code / g++

三、代码实现
3.3 矿工Bob
在3.2里我们定义了一个居民类,表示小镇上的居民都具有的一些共同特征。之后,我们又将构建一个“矿工类”,这个类描述了“矿工”的属性、状态和行为,是一个真正意义上的智能体。
Bob会渴,会饿,会走来走去,会睡觉,会挖矿。这些都是有别于其他居民的特征和行为,也是他作为一个游戏智能体的存在条件。虽然比较简单。
这里,我们需要用到c++的特性之一,继承。
类继承能够从已有的类派生出新的类,而派生类继承了原有类(称为基类)的特征,包括方法。
----《C++ Primer Plus》
继承的目的之一,就是为了提高代码的重用性。这样,不管我们创建多少个“矿工Bob”,都可以只用同一套代码来表示他们的共性。而不用每个人都写一遍。
3.3.1 Miner类实现

可见,Miner类公开继承了BaseGameEntity类,也就是说每个Miner类都会有一个ID和Update()函数,由于Update()函数是纯虚函数,因此它不用在基类中实现,但是一定要在派生类中被覆盖且实现。
方框里是Miner类的一些行为函数,当Bob处在某个状态中时,他的一些属性会发生变化,这些改变通过方框里的函数来实现。
其中某些函数用到了关键字const,用来定义一个不会被改变的常量,可修饰 普通变量、指针、函数参数和类的成员函数。
const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值。

图11是Miner类的初始化,除了必须有的id之外,注意我们一开始也是要给Miner类一个初始状态GoHomeAndSleepTilRestted::Instance() ,这个类就是接下来要讲的具体状态类。
目前,一个矿工只有四种状态,也即一个Miner类有四个具体状态类。
其中,我们重点了解一下Update()和ChangeState()的实现:
Update()函数被用来更新Bob的状态,每个时刻执行一次,每次执行的时候饥渴值+1,同时执行当前状态的Excute()函数。之所以这样做,是因为我们用状态模式,将具体状态类从Miner类中分离了出去,并用单例模式来实现,因此Miner类只能通过Update()来更新状态。

ChangeState()函数被用来改变Bob的状态,只有当满足某种条件之后才会执行。我们规定每次改变状态的时候,都要先用Exit()来退出当前的状态,再通过Enter()来进入新的状态。

最后一点,我们额外定义了一个枚举类型来存储Bob的位置,方便记忆和操作:


知识点:
类的实现 & 类的初始化方式
继承
const关键字的用法
枚举类型

参考:
《游戏人工智能编程案例精粹》
《C++ Primer Plus》
相关代码下载:https://github.com/linpeijie/GameToy/tree/master/GameAI/FSM