实现简易而强大的游戏AI——FSM,有限状态机
http://blog.friskit.me/2012/05/introduction-of-fsm/
在很久很久以前,受限于计算机性能和图形效果,游戏往往是以玩家为唯一主动对象的,玩家发出动作,游戏响应结果。除此之外,不需要系统在玩家没有发出动作时产生响应。可以说,玩家的动作与游戏是“同步”的。
随着计算机的处理能力的发展,更绚丽的游戏逐渐产生。玩家就不能只满足盯着屏幕上静态的一张张图片进行游戏。也就是说,游戏应该有自己的方式能够与玩家主动沟通。这样才能使游戏更加生动,虚拟的环境显得更加真实。游戏上非玩家角色(NPC)应该有着自己独立的动作。
像星际争霸这类RTS游戏推动了游戏AI产业的发展。游戏AI的编写方法也逐渐规范。
最早,游戏AI往往是这样写的:
switch(自己){
|
血量充足就要去打怪,快死了就补血,彻底死了游戏就结束。
把这个代码放到一个无限死循环里头,好了,这个游戏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伪代码:
/** |
然后就是要实现状态
public class StateA extends FSMState{
|
从上面的介绍中我们很容易归纳出一套FSM比较通用的一般步骤:
1,确定状态
2,列举感知数据
3,分别编写状态Update逻辑
4,确定转移状态的条件。
实现简易而强大的游戏AI——FSM,有限状态机的更多相关文章
- 使用行为树(Behavior Tree)实现游戏AI
——————————————————————— 谈到游戏AI,很明显智能体拥有的知识条目越多,便显得更智能,但维护庞大数量的知识条目是个噩梦:使用有限状态机(FSM),分层有限状态机(HFSM),决策 ...
- 趣说游戏AI开发:对状态机的褒扬和批判
0x00 前言 因为临近年关工作繁忙,已经有一段时间没有更新博客了.到了元旦终于有时间来写点东西,既是积累也是分享.如题目所示,本文要来聊一聊在游戏开发中经常会涉及到的话题--游戏AI.设计游戏AI的 ...
- 如何建立一个完整的游戏AI
http://blog.friskit.me/2012/04/how-to-build-a-perfect-game-ai/ 人工智能(Artificial Intelligence)在游戏中使用已经 ...
- 对弈类游戏的人工智能(5)--2048游戏AI的解读
前言: 闲得没事, 网上搜"游戏AI", 看到一篇<<2048游戏的最佳算法是?来看看AI版作者的回答>>的文章. 而这篇文章刚好和之前讲的对弈类游戏AI对 ...
- 游戏AI之初步介绍(0)
目录 游戏AI是什么? 游戏AI和理论AI 智能的假象 (更新)游戏AI和机器学习 介绍一些游戏AI 4X游戏AI <求生之路>系列 角色扮演/沙盒游戏中的NPC 游戏AI 需要学些什么? ...
- 游戏AI的综合设计
原地址:http://www.cnblogs.com/cocoaleaves/archive/2009/03/23/1419346.html 学校的MSTC要出杂志,第一期做游戏专题,我写了一下AI, ...
- 游戏AI系列内容 咋样才能做个有意思的AI呢
游戏AI系列内容 咋样才能做个有意思的AI呢 写在前面的话 怪物AI怎么才能做的比较有意思.其实这个命题有点大,我作为一个仅仅进入游戏行业两年接触怪物AI还不到一年的程序员来说,来谈这个话题,我想我是 ...
- html5 canvas简易版捕鱼达人游戏源码
插件描述:html5利用canvas写的一个js版本的捕鱼,有积分统计,鱼可以全方位移动,炮会跟着鼠标移动,第一次打开需要鼠标移出背景图,再移入的时候就可以控制炮的转动,因为是用的mouseover触 ...
- 对弈类游戏的人工智能(4)--游戏AI的落地
前言: 对弈类游戏的智能算法, 网上资料颇多, 大同小异. 然而书上得来终觉浅, 绝知此事要躬行. 结合了自己的工程实践, 简单汇总整理下. 一方面是对当年的经典<<PC游戏编程(人机博弈 ...
随机推荐
- uC/OS-II互斥信号(OS_mutex)块
/*************************************************************************************************** ...
- linux配置IP的方法
Linux系统下如何设置IP地址?我们可以通过命令设定IP的方法,不过此方法的前提条件是用户需root权限.在Linux系统的 /etc/sysconfig/network-script/ifcfg- ...
- easyUI validate函数【总结篇-部分转】
以下是自己总结和修改别人的帖子和资源整理出来的一些常用验证函数,备用,交流. <body>邮箱验证:<input type="text" validtype=&q ...
- linux curl 命令详解,以及实例
linux curl是一个利用URL规则在命令行下工作的文件传输工具.它支持文件的上传和下载,所以是综合传输工具,但按传统,习惯称url为下载工具. 一,curl命令参数,有好多我没有用过,也不知道翻 ...
- Ankh不起作用的解决方法
请检查Visual Studio 2008的Tool > Options... > Source Control,在下拉菜单中选择插件.
- 以全局监听的方式处理img的error事件
http://www.ovaldi.org/2015/09/11/%E4%BB%A5%E5%85%A8%E5%B1%80%E7%9B%91%E5%90%AC%E7%9A%84%E6%96%B9%E5% ...
- Js获取指定Url参数
在 C#.PHP.JSP 中,都有直接获取 Url 中指定参数的方法,但 Javascript 却没有这样的现在方法,得自己写一个.在 Web 的开发过程中,获取 Url 中的参数是十分常用的操作,所 ...
- DIV CSS 网页兼容全搞定 (IE6 IE7 IE8 IE9 火狐 谷歌)
CSS兼容常用技巧 请尽量用xhtml格式写代码,而且DOCTYPE影响 CSS 处理,作为W3C标准,一定要加DOCTYPE声明. 1.div的垂直居中问题 vertical-align:middl ...
- 项目管理知识框架PMBOK(文字版)
项目管理知识框架PMBOK 项目整体管理[I](Integration) 1. 制定项目章程(Develop Project Charter) 2. 制定项目初步范围说明书(Develop Pre ...
- 测试LVS+Keepalived高可用负载均衡集群
测试LVS+Keepalived高可用负载均衡集群 1. 启动LVS高可用集群服务 此时查看Keepalived服务的系统日志信息如下: [root@localhost ~]# tail -f /va ...