Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4999531
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2012-10-22 11:35:17

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函数:

  1. StateName( Event, StateData ) ->

  2.     .. 这里放动作的代码 ...

  3.     { next_state, StateName', StateData' }


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

  1. -module(npc).
  2.   
  3. -behaviour(gen_fsm).
  4.   
  5. %% API
  6. -export([start_link/0]).
  7.   
  8. %% gen_fsm callbacks
  9. -export([init/1, static/2, moving/2, handle_event/3,
  10.      handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
  11.   
  12. -export([hero_join/0, hero_leave/0]).
  13.   
  14. -define(SERVER, ?MODULE).
  15.   
  16. -record(npc, {state}).
  17.   
  18. start_link() ->
  19.     gen_fsm:start_link({local, ?SERVER}, ?MODULE, [], []).
  20.   
  21. %% 初始化NPC为静止状态
  22. init([]) ->
  23.     io:format("init...~n"),
  24.     State = #npc{state = static},
  25.     io:format("init State: ~p~n", [State]),
  26.    {ok, static, State}.
  27.   
  28. %% 英雄进入视野
  29. hero_join() ->
  30.     gen_fsm:send_event(?SERVER, hero_join).
  31.   
  32. %% 英雄离开视野
  33. hero_leave() ->
  34.     gen_fsm:send_event(?SERVER, hero_leave).
  35.   
  36. %% 静止状态下,接受来自客户端的事件
  37. static(Event, State) ->
  38.     case Event of
  39.     hero_join -> %% 英雄进入视野
  40.         do_moving(), %% 执行动作
  41.         NewState = State#npc{state = moving},
  42.         io:format("npc set state: ~p~n", [NewState]),
  43.         {next_state, moving, NewState}
  44.     end.
  45.   
  46. %% 移动状态下,接受来自客户端的事件
  47. moving(Event, State) ->
  48.     case Event of
  49.     hero_leave -> %% 英雄离开视野
  50.         do_static(), %% 执行动作
  51.         NewState = State#npc{state = static},
  52.         io:format("npc set state: ~p~n", [NewState]),
  53.         {next_state, static, NewState}
  54.     end.
  55.   
  56. handle_event(_Event, StateName, State) ->
  57.     {next_state, StateName, State}.
  58.   
  59. handle_sync_event(_Event, _From, StateName, State) ->
  60.     Reply = ok,
  61.     {reply, Reply, StateName, State}.
  62.   
  63. handle_info(_Info, StateName, State) ->
  64.     {next_state, StateName, State}.
  65.   
  66. terminate(_Reason, _StateName, _State) ->
  67.     ok.
  68.   
  69. code_change(_OldVsn, StateName, State, _Extra) ->
  70.     {ok, StateName, State}.
  71.   
  72. %% NPC 开始移动,进入移动状态
  73. do_moving() ->
  74.     io:format("npc beigin moving...~n").
  75.   
  76. %% NPC 停止移动,进入静止状态
  77. do_static() ->
  78.     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 时的处理是类似的,这里就不重复表述了。

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

 

文章来自:http://www.cnblogs.com/yourihua/archive/2012/05/13/2497776.html


 

 

 

阅读(1053) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~