http://blog.friskit.me/2012/05/introduction-of-fsm/

在很久很久以前,受限于计算机性能和图形效果,游戏往往是以玩家为唯一主动对象的,玩家发出动作,游戏响应结果。除此之外,不需要系统在玩家没有发出动作时产生响应。可以说,玩家的动作与游戏是“同步”的。

随着计算机的处理能力的发展,更绚丽的游戏逐渐产生。玩家就不能只满足盯着屏幕上静态的一张张图片进行游戏。也就是说,游戏应该有自己的方式能够与玩家主动沟通。这样才能使游戏更加生动,虚拟的环境显得更加真实。游戏上非玩家角色(NPC)应该有着自己独立的动作。

像星际争霸这类RTS游戏推动了游戏AI产业的发展。游戏AI的编写方法也逐渐规范。

最早,游戏AI往往是这样写的:

switch(自己){
case "血量充足":
打怪();
break;
case "快死了":
补血();
break;
case "死了":
游戏全局->Gameover();
break;
}

血量充足就要去打怪,快死了就补血,彻底死了游戏就结束。
把这个代码放到一个无限死循环里头,好了,这个游戏AI就算做成了。把这东西放到代码里头,提交,然后等老板发工资。

但是老板突然说:“你这个AI写的太简单了”。然后又balabala提了一大堆需求:
老板又让你加上这些功能:血量80的时候用魔法补一补就行了,血量60的时候吃个小血瓶,血量40的时候吃大血瓶,血量20的时候赶快逃跑。

然后你又要找到上面这个switch,然后修改里头的case。想象一下,万一你碰到了一个Dota高手当老板,心中有着各种很NB的杀敌策略,你需要虽是根据环境判断利用那种策略。策略越来越多,很快,一个带有上万行代码的函数就横空出世了!如果这个时候遇到bug了,先别说怎么改了,光把这个几M的源代码打开都够费劲的吧?然后,然后你就没有然后了。。。

上面的方法在遇到大量的状态(State)的时候会让代码崩溃,好在有无数前辈前仆后继用各种切身体会帮我们提出了一种又一种精简代码的手段。

不知大家有多少人学过数字电路。学过里面的“状态图”?
在时序电路里头,一个系统往往由一堆状态组成,从状态A,通过输入,跳转到状态B。这就是状态图。例如下面的图片:

上面这种方法就被称作“有限状态机”(FSM,Finite State Machine)。那么究竟什么是FSM?

·FSM是一种数据结构,它由以下几个部分组成:

1,内在的所有状态(必须是有限个)

2,输入条件

3,状态之间起到连接性作用的转换函数

·为什么要用FSM?

因为它编程快速简单,易于调试,性能高,与人类思维相似从而便于梳理,灵活且容易修改

·FSM的描述性定义:

一个有限状态机是一个设备,或是一个模型,具有有限数量的状态。它可以在任何给定时间根据输入进行操作,使得系统从一个状态转换到另一个状态,或者是使一个输出或者一种行为的发生,一个有限状态机在任何瞬间只能处于一种状态。

·挖掘状态

例如我们有这样一个场景。玩家控制一个Hero打怪练级。这个英雄等级不够没啥经验带上典型的阿Q精神,所以基本上只有这三个动作:
1,平时的状态是巡逻,就是漫无目的的走。。。
2,如果遇到敌人之后大量一下敌人。
3,如果敌人比自己弱小,那就打。
4,如果敌人比自己强大,那就跑。

根据上面的需求我们能画出这样一张状态图:

我对FSM的基本解释:一个智能体,在有规则的时间间隔内询问现在所掌握的环境数据,使得它能够基于从游戏环境中接受到的刺激进行必要的状态转换。每一个状态可以模型化为一个分离的对象,或者存在于智能体外部的函数。

这样,FSM提供给了我们一个清楚灵活的结构。

·FSM一般骨架代码

一般FSM中需要有以下几个类作为一种数据框架:
FSMState类:抽象类,表示基本状态,所有状态都应该继承自这个类
FSMMachine类:一台有限状态机
FSMAIControl类:存放有限状态机,通常就是游戏AI的主循环。并且能存放环境感知数据等内容。

下面是Java伪代码:

/**
*FSMState:
*/
public abstract class FSMState{
public FSMAIControl m_parent;
public int m_type;
 
public abstract void Enter(); //状态进入时执行动作
public abstract void Exit(); //状态退出时执行动作
public abstract void Update(); //游戏主循环中状态的内部执行机制
public abstract void Init(); //状态的初始化
public FSMState CheckTransition(); //状态转移判断
}
 
/**
*FSMMachine
*/
public class FSMMachine{
private ArrayList<FSMState> m_states;
private FSMState m_currentState;
private FSMState m_defaultState;
private FSMState m_goalState;
private int m_goalID;
 
public void UpdateMachine(); //更新状态机状态
public void AddState(FSMState state); //给状态机添加状态
public void SetDefaultState(FSMState state); //设置默认状态
public void SetGoalID(int goal); //设置目标状态
public void TransitionState(int goal); //状态转移
public void Reset(); //状态重置
}
 
/**
*FSMAIControl
*/
public class FSMAIControl{
public … //游戏感知数据
private FSMMachine m_machine;
 
public void Update();
public void UpdatePerceptions();
public void Init();
}

然后就是要实现状态

public class StateA extends FSMState{
public void Update(){};

 
FSMState CheckTransitions(){
if(parent.xxx=xxx) //判断感知数据
return StateB;
}

}

从上面的介绍中我们很容易归纳出一套FSM比较通用的一般步骤:
1,确定状态
2,列举感知数据
3,分别编写状态Update逻辑
4,确定转移状态的条件。

实现简易而强大的游戏AI——FSM,有限状态机的更多相关文章

  1. 使用行为树(Behavior Tree)实现游戏AI

    ——————————————————————— 谈到游戏AI,很明显智能体拥有的知识条目越多,便显得更智能,但维护庞大数量的知识条目是个噩梦:使用有限状态机(FSM),分层有限状态机(HFSM),决策 ...

  2. 趣说游戏AI开发:对状态机的褒扬和批判

    0x00 前言 因为临近年关工作繁忙,已经有一段时间没有更新博客了.到了元旦终于有时间来写点东西,既是积累也是分享.如题目所示,本文要来聊一聊在游戏开发中经常会涉及到的话题--游戏AI.设计游戏AI的 ...

  3. 如何建立一个完整的游戏AI

    http://blog.friskit.me/2012/04/how-to-build-a-perfect-game-ai/ 人工智能(Artificial Intelligence)在游戏中使用已经 ...

  4. 对弈类游戏的人工智能(5)--2048游戏AI的解读

    前言: 闲得没事, 网上搜"游戏AI", 看到一篇<<2048游戏的最佳算法是?来看看AI版作者的回答>>的文章. 而这篇文章刚好和之前讲的对弈类游戏AI对 ...

  5. 游戏AI之初步介绍(0)

    目录 游戏AI是什么? 游戏AI和理论AI 智能的假象 (更新)游戏AI和机器学习 介绍一些游戏AI 4X游戏AI <求生之路>系列 角色扮演/沙盒游戏中的NPC 游戏AI 需要学些什么? ...

  6. 游戏AI的综合设计

    原地址:http://www.cnblogs.com/cocoaleaves/archive/2009/03/23/1419346.html 学校的MSTC要出杂志,第一期做游戏专题,我写了一下AI, ...

  7. 游戏AI系列内容 咋样才能做个有意思的AI呢

    游戏AI系列内容 咋样才能做个有意思的AI呢 写在前面的话 怪物AI怎么才能做的比较有意思.其实这个命题有点大,我作为一个仅仅进入游戏行业两年接触怪物AI还不到一年的程序员来说,来谈这个话题,我想我是 ...

  8. html5 canvas简易版捕鱼达人游戏源码

    插件描述:html5利用canvas写的一个js版本的捕鱼,有积分统计,鱼可以全方位移动,炮会跟着鼠标移动,第一次打开需要鼠标移出背景图,再移入的时候就可以控制炮的转动,因为是用的mouseover触 ...

  9. 对弈类游戏的人工智能(4)--游戏AI的落地

    前言: 对弈类游戏的智能算法, 网上资料颇多, 大同小异. 然而书上得来终觉浅, 绝知此事要躬行. 结合了自己的工程实践, 简单汇总整理下. 一方面是对当年的经典<<PC游戏编程(人机博弈 ...

随机推荐

  1. HTTPS 客户端验证 服务端证书流程

    网上的文章很多, 但是对摘要的验证流程不够通俗易懂. QQ截图20160420114804.png 证书预置和申请 1:客户端浏览器会预置根证书, 里面包含CA公钥2:服务器去CA申请一个证书3: C ...

  2. mongodb嵌套查询

    db.dbModel.find({'Missions.Rewards.PrizeType':21} )

  3. hibernate实现有两种配置,xml配置与注释配置。

    (1):xml配置:hibernate.cfg.xml (放到src目录下)和实体配置类:xxx.hbm.xml(与实体为同一目录中) <?xml version='1.0' encoding= ...

  4. JavaScript排序算法——归并排序

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. Linux学习笔记(二)2015.4.14

    笔记2.1 Q:登陆命令  A:刚开始登陆的是安装Linux时设置的普通用户,如lin,输入su - root后,成为root用户 笔记2.2 Q:切换控制台  A:ctrl+alt+F1-F7可以切 ...

  6. github打不开

    所用方法:修改host文件 一.键入网址:http://github.global.ssl.fastly.net.ipaddress.com/#ipinfo 拿到github.global.ssl.f ...

  7. JAVA个人知识总结

    1.一个.java文件中只能有一个public类,且必须跟文件名相同,其他类不能以public开头. 2.继承: 子类继承父类的属性和方法. 3.继承和组合: 继承是对“是一种”(is-a)关系建模, ...

  8. OC- .h与.m

    1.只有利用类名调用类方法的时候,不需要在类名后面写*.其他情况下,类名后面统一加上一个* Circle *c1 = [Circle new]; - (BOOL)isInteractWithOther ...

  9. Orchard源码分析(1):Orchard架构

      本文主要参考官方文档"How Orchard works"以及Orchardch上的翻译.   源码分析应该做到庖丁解牛,而不是以管窥豹或瞎子摸象.所以先对Orchard架构有 ...

  10. ASP.NET MVC使用Bootstrap系列(1)——开始使用Bootstrap

    阅读目录 Bootstrap结构介绍 在ASP.NET MVC 项目中添加Bootstrap文件 为网站创建Layout布局页 使用捆绑打包和压缩来提升网站性能 在Bootstrap项目中使用捆绑打包 ...