简述游戏开发中的状态机

为什么我们需要状态机

实行较多状态的角色,把动作全写在一个部分中会导致维护成本高,拓展性低
例如:走路,跳跃,射击,躲避的相互转换,有些可以转换,有些不能,实现逻辑复杂
(满屏幕都是if - else)

状态模式switch实现

//包含着所有的状态
enum class State{StateA, StateB, StateC, ...} activeState;
...
//通过switch语句切换状态,根据具体情况实现细节
switch (activeState)
{
    case State.StateA:
        ...
        break;
    case State.StateB:
        ...
        break;
    .......
}
...

状态机的原形,用一个枚举表示当前的状态,通过填充完善switch语句实现状态之间的切换,但是依然有维护成本高拓展低的缺点(虽然确实是比用if - else堆好)

Finite State Machine(FSN)有限状态机

最基本的状态机,一般来说其他状态机都是这种状态机的变体
对于状态机的理解,最好就是画个图(如图结构,方框是状态,箭头是状态之间的联系)

有限状态机强调的是状态之间的切换,以及对不同状态的封装,所以实现方法一般可以根据需求调整
以下参考了《游戏人工智能》的实现
首先需要个基类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()获得的状态

然后还有状态机类,用来管理所有状态:

//状态机类
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();
}

接下来具体的状态细节就要具体继承,具体实现

Hierarchical Finite State Machine (HFSM) 分层状态机

分层状态机相当于对有限状态机的进一步封装,将复数个状态封装成一个大的状态,再用一个“历史状态”记录切出此状态时运行的子状态,就可以在大状态间切换(结构如图)

图中将StateA和StateB加入到一个更高层的状态StateD中,只需退出时记录状态,就可以在CD状态间切换,增加了状态C的复用性(省略了AC,BC间的联系)
主要思想一是包装更高的层次,二是高层的切换放到更高层来觉得以提高复用
分层状态机的实现主要分两种:
一、父状态就是一个状态机,可以往里面添加状态
二、添加一个状态栈储存父子状态,每一个状态都是栈下一个状态的子状态,进入状态时入栈,结束状态时出栈并发送一个消息,新栈顶状态不能处理就再出栈,直到栈顶状态能处理这个消息为止。

并发状态机

并发状态机可以理解为一个对象拥有两个同时运作的状态机,两个状态机相互独立(但可以通过修改对象的状态进行通信),例如我们可以将腿部动作(站立,下蹲,奔跑)和手部动作(持枪,空手,瞄准)分离。

下推状态机

下推状态机的核心是他有一个状态栈(但和层次状态机实现的栈完全不同,层次状态机的栈是为了记录父状态,这个栈是为了纪录上一个状态)。
状态栈主要解决的是状态机无法得到上一轮执行的状态。
实现时,在状态机中加一个栈,在进入状态时将状态入栈,退出状态时将状态出栈,运行时则运行栈顶的状态。
例如,我在做作业的时候饿了,想去吃东西。饿了去吃东西是多数状态都能进入的状态,并且结束“吃东西”的状态后我要回复原来的状态。

在运行时,状态机已经将“做作业“入栈
然后“我饿了”,将“吃东西”入栈
“吃东西”结束,将“吃东西”出栈
继续运行栈顶的“做作业”(事实上不可能)

若有错误,欢迎指出

原文地址:https://www.cnblogs.com/yasoudream/p/11802866.html

时间: 2024-11-02 04:15:51

简述游戏开发中的状态机的相关文章

6_State 游戏开发中使用状态机

### State 不好的代码 ``` //处理玩家输入的代码 void Heroine::handleInput(Input input) { if (input == PRESS_B) { if (!isJumping_ && !isDucking_) { // Jump... } } else if (input == PRESS_DOWN) { if (!isJumping_) { isDucking_ = true; setGraphics(IMAGE_DUCK); } else

FSM:游戏开发中的有限状态机(理论篇)转

游戏系统的本质是输入加输出.我们把游戏系统划分为多个不同状态,不同的状态在不同输入下产出不同输出.按照这种思想,我们可以把游戏中复杂的子系统,比如战斗系统,划分成多个不同状态,然后我们要做的只是,对于不同的战斗操作输入,转换相应状态,执行相应状态下的动作输出. 那么什么是有限状态机? 我们要说的状态机输入和输出都是离散的.有限的:在这个基础上,我们所说的有限状态机就是描述这一类问题:在有限的输入里,由于不同的输入时序产生的有限的输出组合的映射关系.要描述这种映射关系,有两种表达方式: 状态迁移表

游戏开发中,图片资源的精简

在游戏开发中,包的大小总是与图片资源的大小密切相关,而图片资源中,大多为带有透明度信息的png图像. 那么,如何精简png图片资源呢? 1.图像压缩是一种方法,然而随着压缩率的增大.图片品质也越来越差.(舍弃) 2.我们另辟蹊径,采用png图像拆分.(近乎无损,资源精简) 一.原理:将png图像转化为两张jpeg图像进行存储 pngSplit下载 pngSplit使用说明 二.使用方法: 1.LibGdx中,通过Pixmap使用 // 如工程目录assets/texture/0_1.jpeg下:

游戏开发中的人工智能 复习

游戏开发中的人工智能 复习 (个人复习,一些仅是给自己的复习提示(=w=),转载注明出处:http://blog.csdn.net/hcbbt/article/details/42815479) 配套教材:游戏开发中的人工智能 知识点 移动 Bresenham,视线(略),拦截 // Bresenham if (deltaCol > deltaRow) { fraction = deltaRow * 2 - deltaCol; while (nextCol != endCol) { if (fr

&lt;游戏开发中的人工智能&gt; -- 阅读笔记

到家已经几天了, 休息了一阵, 是时候重新学习知识了. 接下去一段时间, 会啃<游戏开发中的人工智能>这本书, 顺便写写笔记. 马上就大三了, 想想自己选的游戏方向, 现在还蛋疼. 选了一个自己喜欢的方向, 但是确实最忙的一个,这也意味着少时间继续我的iOS学习. 也不知道是对是错. 既然选了,就学吧. 好不,不扯多了.接下去是该系列的笔记.(持续更新) 第一章: 游戏人工智能简介 1. 定性AI与非定性AI 定性行为或其表现是特定的,而且是可预测的,没有不确定性. 非定性行为有某种程度的不确

游戏开发中的一些基本方法

一.              检测对象变化的两种基本方式: 学过<微机原理>的人应该都了解这两种方式 1.       轮询 1) 每帧轮询 2) 定时轮询 按业务需求和性能问题选择 2.       中断(并非硬件中断,而是软件的事件通知方式) 两种模式: 1)       观察者模式 优点:① 扩展性强,事件发起接口不变,只需增加事件类型 ② 只通知对某件事有兴趣的对象,不会浪费性能 ③ 每种事件对应一种回调函数,对于回调函数,事件参数类型是固定的,MouseMove事件的参数类型肯定是

c++实现游戏开发中常用的对象池(含源码)

c++实现游戏开发中常用的对象池(含源码) little_stupid_child2017-01-06上传 对象池的五要素: 1.对象集合 2.未使用对象索引集合 3.已使用对象索引集合 4.当前使用量 5.最大使用量 http://download.csdn.net/download/little_stupid_child/9730912

Cocos2d-x手机游戏开发中-组合动作

动作往往不是单一,而是复杂的组合.我们可以按照一定的次序将上述基本动作组合起来,形成连贯的一套组合动作.组合动作包括以下几类:顺序.并列.有限次数重复.无限次数重复.反动作和动画.动画我们会在下一节介绍,本节我们重点顺序.并列.有限次数重复.无限次数重复和反动 下面我们通过一个实例介绍一下组合动作的使用,这个实例如下图所示,下图是一个操作菜单场景,选择菜单可以进入到下图动作场景,在下图动作场景中点击Go按钮可以执行我们选择的动作效果,点击Back按钮可以返回到菜单场景. 下面我们再看看具体的程序

游戏开发中的矩阵初探

游戏开发中的矩阵初探 1.矩阵在3d空间中的作用 (1)长方体A想绕(10,3,4)旋转50°且沿着x方向放大2倍且向(9,-1,8)方向平移2个单位,那么经过上面的变换后,新的长方体各个点的坐标是多少呢?应用矩阵可以很轻松的算出答案. (2)知道子坐标系在父坐标系中的位置,可以求出子坐标系中的店在父坐标系中的位置. 2.矩阵的基础知识 矩阵能描述任意线性变换.线性变换保留了直线和平行线,线性变换保留直线的同时,其他的几何性质如长度.角度.面积和体积可能被变换改变了.简单的说,线性变换可能“拉伸