所谓定义:
“有限状态机就是一个具有有限数量状态,并且能够根据相应的操作从一个状态变换到另一个状态,而在同一时刻只能处在一种状态下的智能体。”(来自google----《Android游戏开发大全》)
游戏中的有限状态机是一个由多种状态组成的机制。
他包括:
1.状态:多种互斥的状态元素,某个实体同时只能处于一个状态之中
2.刺激: 这个“刺激”可以影响状态的改变
3.转换机制:状态间转换的处理机制。 {
输入状态的处理;
输出状态的处理
}
有了这种划分,具体到代码逻辑上,思路就会更清晰:
1.状态
对于每种状态,都相当于该实体当前时刻的自己,需要有一个update以进行本身的逻辑,以game为例,假设有kPrepare,kRunning,kEnd三种状态(注:状态元素通过枚举类型的命名,要比单纯的整型在代码的可读性上高的多)。状态部分的实现,会类似于:
void Update(float time) {
switch(state_) {
case kPrepare:
...;
break;
case kRunning:
...;
break;
case kEnd:
...;
break;
}
}
2.刺激
有限状态机用于被动触发。他需要收到一个刺激,以启动自己。这个刺激或许来自内部,或许来自外部。
例如:游戏开始在kPrepare状态,当准备时间结束后,game切换到了kRunning状态( SetState(kRunning) );这是内部的刺激,来自于kPrepare状态的update之中
游戏在kRunning状态时,玩家点击退出,game切换到了kEnd状态( SetState(kEnd) );这是来自外部的刺激,可能处在于一个void EndGame()的对外接口之中。
3.转换机制
状态间的转换机制,是有限状态机的核心。
void SetState(int state) { //同种状态不切换 if(state_ == state) { return; } //要离开的状态的处理 switch(state_) { case kPrepare://对于准备状态,在离开它之前,需要将准备倒计时清零,隐藏倒计时 ...; break; case kRunning://运行状态,离开它之前,要暂停游戏 ...; break; case kEnd://结束状态,离开之前,需要隐藏结算界面 ...; break; } //要进入的状态的处理 switch(state) { case kPrepare://准备状态,进入它之前,需要显示倒计时 ...; break; case kRunning://运行状态,进入它之前,要开始游戏 ...; break; case kEnd://结束状态,进入它之前,要显示结算界面 ...; break; } state_ = state;//完成状态转换
} 状态机通过将每种状态做“进入”和“退出”两种处理,分割了状态之间的联系。
每个状态只需要关注自己的变化(update),在受到特定的刺激之后,完成自己的“退出”处理,进入新状态的“进入”处理。
4.技巧
1.实体既然有状态机,则在任意时刻,都必需处于某个状态中。update中所有的变化,也必须都在某状态之下,不能有变化凌驾于switch之外。(除非是子实体,它由它自己的状态机控制行为)
2.如果实体需要在初始化的时候就进行一次SetState,则在实体构造的时候,将state_ = kInvalidate,状态就可以正常的从“不可用”转换到“初始”。