博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Erlang OTP设计原则Gen_Fsm行为
阅读量:4558 次
发布时间:2019-06-08

本文共 2872 字,大约阅读时间需要 9 分钟。

  1. Fsm 称为 有限状态机,举个例子,游戏中的怪物称为NPC,NPC一般有几种状态,比如:静止,移动,死亡,被攻击,攻击英雄等等几个有限的状态,那么我们就可以有限状态机实现NPC的状态变更。

  一个有限状态机可以用一个关系式来描述,State(静止状态S1) x Event(英雄进入视野范围事件E) -> Actions(开始移动动作A), State(移动状态S2)

  解释如下:当一个NPC处于静止状态S1,有一个英雄进入NPC视野范围时E,会触发NPC开始移动动作A,并且NPC转变状态为移动状态S2

  对于一个用 gen_fsm 行为实现的FSM来说,状态转换规则被写为符合如下约定的一系列Erlang函数:

StateName( Event, StateData ) ->    .. 这里放动作的代码 ...    { next_state, StateName', StateData' }

  2. 接下来我们来看个例子,游戏中NPC状态变化,当然我做了很大的简化,真正游戏中的逻辑比这复杂的多。这里我只是为了说明,erlang OTP设计原则中的gen_fsm如何使用,代码如下:

-module(npc).-behaviour(gen_fsm).%% API-export([start_link/0]).%% gen_fsm callbacks-export([init/1, static/2, moving/2, handle_event/3,	 handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).-export([hero_join/0, hero_leave/0]).-define(SERVER, ?MODULE).-record(npc, {state}).start_link() ->    gen_fsm:start_link({local, ?SERVER}, ?MODULE, [], []).%% 初始化NPC为静止状态init([]) ->    io:format("init...~n"),    State = #npc{state = static},    io:format("init State: ~p~n", [State]),   {ok, static, State}.%% 英雄进入视野hero_join() ->    gen_fsm:send_event(?SERVER, hero_join).%% 英雄离开视野hero_leave() ->    gen_fsm:send_event(?SERVER, hero_leave).%% 静止状态下,接受来自客户端的事件static(Event, State) ->    case Event of	hero_join -> %% 英雄进入视野	    do_moving(), %% 执行动作	    NewState = State#npc{state = moving},	    io:format("npc set state: ~p~n", [NewState]),	    {next_state, moving, NewState}    end.%% 移动状态下,接受来自客户端的事件moving(Event, State) ->    case Event of	hero_leave -> %% 英雄离开视野	    do_static(), %% 执行动作	    NewState = State#npc{state = static},	    io:format("npc set state: ~p~n", [NewState]),	    {next_state, static, NewState}    end.handle_event(_Event, StateName, State) ->    {next_state, StateName, State}.handle_sync_event(_Event, _From, StateName, State) ->    Reply = ok,    {reply, Reply, StateName, State}.handle_info(_Info, StateName, State) ->    {next_state, StateName, State}.terminate(_Reason, _StateName, _State) ->    ok.code_change(_OldVsn, StateName, State, _Extra) ->    {ok, StateName, State}.%% NPC 开始移动,进入移动状态do_moving() ->    io:format("npc beigin moving...~n").%% NPC 停止移动,进入静止状态do_static() ->    io:format("npc stop moving, join static...~n").

   代码注释比较详细,接下来可以通过运行代码,来好好理解下这个例子,

  1. 首先,调用 npc:start_link(). 来初始化NPC服务;这个时候NPC处于静止状态 static;

  2. 当npc处于静止状态时,我们通过调用 npc:hero_join().来表示有一个侠客进入NPC的视野,那么这个时候gen_fsm会默认调用当前gen_fsm处于的状态,也就是static的处理方法,也就是 static(Event, State) 这个函数,这边可能比较绕,我已经尽量去用直白的语言来表达,能力有限,大家多思考下,呵呵;

  3. 当处理 static 函数时,Event 这个变量,就是 gen_fsm:send_event(?SERVER, hero_join). hero_join,紧接着执行对应的动作,在这里也就是 do_moving(),开始移动;

  4. 最后,我们需要返回 {next_state, moving, NewState} 让gen_fsm进入下一个状态,也就是 moving 状态;

  5. 当npc处于移动时,我们通过调用 npc:hero_leave(). 来表示 该侠客移动NPC的视野,那么对应的 moving(Event, State) 函数就会被调用,其他的处理与 static 时的处理是类似的,这里就不重复表述了。

  这个例子还有一些函数,我没有讲到,希望在以后的教程来跟大家分享,谢谢。

 

 

 

转载于:https://www.cnblogs.com/yourihua/archive/2012/05/13/2497776.html

你可能感兴趣的文章
Binary XML file : Error inflating class com.esri.android.map.MapView
查看>>
grep,awk和sed
查看>>
.NET Core WebAPI IIS 部署问题
查看>>
SystemTap 静态探针安装包
查看>>
redis五种数据类型的使用
查看>>
浏览器全屏之requestFullScreen全屏与F11全屏
查看>>
软件包管理:rpm命令管理-安装升级与卸载
查看>>
旋转图像
查看>>
字符串中的数字(字符串、循环)
查看>>
15.select into
查看>>
缓存-->Java中缓存的原理
查看>>
运行web项目端口占用问题
查看>>
Java Spring-IOC和DI
查看>>
【NOIP1999】【Luogu1015】回文数(高精度,模拟)
查看>>
Linux上安装Python3.5
查看>>
crt安装
查看>>
git切换分支报错:error: pathspec 'origin/XXX' did not match any file(s) known to git
查看>>
c++中static的用法详解
查看>>
转 我修改的注册表,但是程序运行起来,还是记着以前的
查看>>
图片轮播功能
查看>>