〇、先暂停我简单说两句啊
一年前写的文章了,之前更新在 github pages 上,疏于管理,现在觉得还是把这些文档放在 优快云 好了,自己看起来也方便。
2020.5.18 十元
有限状态机是一个很常用的技术,在流程控制和游戏AI中都比较实用,因为状态机编程简单又很符合直觉。本文是参考《Programming Game AI by Example》从零开始使用C++搭一个状态机的轮子,主要有以下几个点:
我会在搭建的过程中穿插一些C++知识的介绍,适合不甚了解C++或是状态机的小伙伴,手把手的编程教程。
- 游戏框架的实现
- 状态类以及游戏对象的状态转换
- 状态机实现
- 消息机制的实现
完整的代码在 github 中给出。
一、
记得最开始工作时候也接触过有限状态机,当时是一个长长的用switch写成的状态机,理解它的时候真的很困难。
所以现在使用一套内置规则到状态内部去,来控制状态的转换。
现在就来制作一个有限状态机。
作为一个关于使用状态机创建一个智能体的实际案例,我们先模拟这样一个场景。想象一个我们控制的角色“我”,在上海延安西路附近工作学习和玩耍,“我”相当的佛系,有钱不愁吃喝就去上学,自由自在地给技能树加点,没钱了就去实习赚外块,渴了累了就近“啤酒阿姨”两瓶啤酒……
但是,这个例子要全靠想象力了,因为这是在控制台中的文本演示。
[图1 这个状态机的示意图,surface画一下,忍一忍买pro7吧]
因此,这个例子中有四个位置:一个学校,可以让“我”提高能力;一个实习公司,根据“我”的能力,给我发实习津贴;一个啤酒阿姨酒吧,让“我”可以解除压力;最后还有一个温馨的家吼,能够解除疲劳。
而这些位置每一个都代表了一个状态,因为我们是使用内置规则来控制状态机的转换,“我”在到达一个位置之后要干什么,都会由当前所处的状态和一些属性值来决定。
&&&&逐个介绍一下,要点的扩展写成补充的blog放到前面,加链接。
BaseGameEntity类,用来作为所有游戏对象的基类,主要为游戏对象提供了一个ID,以及每一帧更新时调用的纯虚函数Update。
class BaseGameEntity
{
private:
int m_ID;
// Should be static
static int m_iNextValidID;
//int m_iNextValidID;
void SetID(int val);
public:
BaseGameEntity(int id)
{
SetID(id);
}
virtual ~BaseGameEntity(){
}
virtual void Update() = 0;
int ID()const {
return m_ID; }
}
使用一个枚举类型管理所有可能到达的地点,sweetHome、school、company、beerLady 分别代表家、学校、实习公司、啤酒阿姨这四个地点。在 Me 类中,对“我”所特有的属性进行了定义,如心情值( m_iMoodForDoingStuffs ),金钱数( m_iMoneyInCard ),能力( m_iAbilityLevel ),疲劳( m_iFatigue ),以及这些属性的阈值,用来在状态转移中起作用。随后定义的方法表明了这些属性如何变化,并为其他类查看这些属性暴露了接口。
enum location_type
{
sweetHome,
school,
company,
beerLady,
};
cla