U3D架构系列之- FSM有限状态机设计五

在设计五中,我们把事件系统EventSystem实现一下。这个EventSystem类主要实现的是事件的注册,触发,以及分发Event消息的作用。提供接口对外使用的。在这里面为了功能扩展方便用了好多模板函数,方便大家调用。

分发消息的时候,我们采用的是队列的方式,就是先进先出原则。

首先要把消息事件注册一下,就是将其放到我们预先定义的表里面。函数代码如下所示:

int Register(string eventName, Func<object,object,object,bool> action) {

   int   listenID = ++mNextListenID;

   Listen  listen = (mFreeListen.Count == 0) ? new Listen() : mFreeListen.Pop();

   listen.mID = listenID;

   listen.mAction = action;

   mRegistered.Add(listenID, listen);

   List<int>  eventList;

   if(!mRegisteredEvents.TryGetValue(eventName, out eventList))

    eventList = mRegisteredEvents[eventName] = new List<int>();

   eventList.Add(listenID);

   return listenID;

  }

接下来就是 消息事件的触发代码如下:

  public void Trigger(string eventName) {

   Call(eventName, null, null, null);

  }
void Call(string eventName, object arg1, object arg2, object arg3) {

   List<int> listenerList;

   if(mRegisteredEvents.TryGetValue(eventName, out listenerList)) {

    for(int i = listenerList.Count - 1; i >= 0; --i) {

     Listen listener;

     if(mRegistered.TryGetValue(listenerList[i], out listener)) {

      if(!listener.mAction(arg1, arg2, arg3)) {

       mRegistered.Remove(listenerList[i]);

       mFreeListen.Push(listener);

       listenerList.RemoveAt(i);

      }

     }

     else {

      listenerList.RemoveAt(i);

     }

    }

    if(listenerList.Count == 0) {

     mRegisteredEvents.Remove(eventName);

    }

   }

  }

 遍历查找消息列表是否在mRegistererdEvents这个字典里面,mRegisteredEvents的定义如下:

Dictionary<string,List<int>>  mRegisteredEvents = new Dictionary<string, List<int>>();

  Listen的定义如下:

  class Listen {

   public int        mID;

   public Func<object,object,object,bool> mAction;

  }

 接下来就是最核心的功能了,状态机的切换功能代码:

public int On<T1,T2,T3>(string eventName, Func<T1,T2,T3,bool> action) {

   return Register(eventName, delegate(object arg1, object arg2, object arg3) {

    T1  param1;

    T2  param2;

    T3  param3;

    try { param1 = (T1)arg1; } catch { param1 = default(T1); }

    try { param2 = (T2)arg2; } catch { param2 = default(T2); }

    try { param3 = (T3)arg3; } catch { param3 = default(T3); }

    return(action(param1, param2, param3));

   });

  }

  

  public int On<T1,T2,T3>(string eventName, Action<T1,T2,T3> action) {

   return Register(eventName, delegate(object arg1, object arg2, object arg3) {

    T1  param1;

    T2  param2;

    T3  param3;

    try { param1 = (T1)arg1; } catch { param1 = default(T1); }

    try { param2 = (T2)arg2; } catch { param2 = default(T2); }

    try { param3 = (T3)arg3; } catch { param3 = default(T3); }

    action(param1, param2, param3);

    return true;

   });

  }

整个的EventSystem事件系统的代码如下所示:

using System;
using System.Collections;
using System.Collections.Generic;
namespace EventSystem {
 public class Dispatcher {  
  public void Trigger(string eventName) {
   Call(eventName, null, null, null);
  }
  
  public void Dispatch(string eventName) {
   Dispatched d = (mFreeDispatch.Count == 0) ? new Dispatched() : mFreeDispatch.Pop();
   mDispatched.Enqueue(d.Set(eventName));
  }
  
  public int On(string eventName, Func<bool> action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    return(action());
   });
  }
  
  public int On(string eventName, Action action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    action();
    return(true);
   });
  }
  
  public void Trigger(string eventName, object param1) {
   Call(eventName, param1, null, null);
  }
  
  public void Dispatch(string eventName, object param1) {
   Dispatched d = (mFreeDispatch.Count == 0) ? new Dispatched() : mFreeDispatch.Pop();
   mDispatched.Enqueue(d.Set(eventName, param1));
  }
  
  public int On<T>(string eventName, Func<T,bool> action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    T  param1;
    try { param1 = (T)arg1; } catch { param1 = default(T); }
    return(action(param1));
   });
  }
  
  public int On<T>(string eventName, Action<T> action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    T  param1;
    try { param1 = (T)arg1; } catch { param1 = default(T); }
    action(param1);
    return true;
   });
  }
  
  public void Trigger(string eventName, object param1, object param2) {
   Call(eventName, param1, param2, null);
  }
  
  public void Dispatch(string eventName, object param1, object param2) {
   Dispatched d = (mFreeDispatch.Count == 0) ? new Dispatched() : mFreeDispatch.Pop();
   mDispatched.Enqueue(d.Set(eventName, param1, param2));
  }
  
  public int On<T1,T2>(string eventName, Func<T1,T2,bool> action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    T1  param1;
    T2  param2;
    try { param1 = (T1)arg1; } catch { param1 = default(T1); }
    try { param2 = (T2)arg2; } catch { param2 = default(T2); }
    return(action(param1, param2));
   });
  }
  
  public int On<T1,T2>(string eventName, Action<T1,T2> action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    T1  param1;
    T2  param2;
    try { param1 = (T1)arg1; } catch { param1 = default(T1); }
    try { param2 = (T2)arg2; } catch { param2 = default(T2); }
    action(param1, param2);
    return true;
   });
  }
  
  public void Trigger(string eventName, object param1, object param2, object param3) {
   Call(eventName, param1, param2, param3);
  }
  
  public void Dispatch(string eventName, object param1, object param2, object param3){
   Dispatched d = (mFreeDispatch.Count == 0) ? new Dispatched() : mFreeDispatch.Pop();
   mDispatched.Enqueue(d.Set(eventName, param1, param2, param3));
  }
  
  public int On<T1,T2,T3>(string eventName, Func<T1,T2,T3,bool> action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    T1  param1;
    T2  param2;
    T3  param3;
    try { param1 = (T1)arg1; } catch { param1 = default(T1); }
    try { param2 = (T2)arg2; } catch { param2 = default(T2); }
    try { param3 = (T3)arg3; } catch { param3 = default(T3); }
    return(action(param1, param2, param3));
   });
  }
  
  public int On<T1,T2,T3>(string eventName, Action<T1,T2,T3> action) {
   return Register(eventName, delegate(object arg1, object arg2, object arg3) {
    T1  param1;
    T2  param2;
    T3  param3;
    try { param1 = (T1)arg1; } catch { param1 = default(T1); }
    try { param2 = (T2)arg2; } catch { param2 = default(T2); }
    try { param3 = (T3)arg3; } catch { param3 = default(T3); }
    action(param1, param2, param3);
    return true;
   });
  }
  
  public bool Cancel(int listenerID) {
   return mRegistered.Remove(listenerID);
  }
  
  public void DispatchPending() {
   while(mDispatched.Count > 0) {
    Dispatched d = mDispatched.Dequeue();
    Call(d.mEventName, d.mArg1, d.mArg2, d.mArg3);
    mFreeDispatch.Push(d);
   }
  }
  
  int Register(string eventName, Func<object,object,object,bool> action) {
   int   listenID = ++mNextListenID;
   Listen  listen = (mFreeListen.Count == 0) ? new Listen() : mFreeListen.Pop();
   listen.mID = listenID;
   listen.mAction = action;
   mRegistered.Add(listenID, listen);
   List<int>  eventList;
   if(!mRegisteredEvents.TryGetValue(eventName, out eventList))
    eventList = mRegisteredEvents[eventName] = new List<int>();
   eventList.Add(listenID);
   return listenID;
  }
  
  void Call(string eventName, object arg1, object arg2, object arg3) {
   List<int> listenerList;
   if(mRegisteredEvents.TryGetValue(eventName, out listenerList)) {
    for(int i = listenerList.Count - 1; i >= 0; --i) {
     Listen listener;
     if(mRegistered.TryGetValue(listenerList[i], out listener)) {
      if(!listener.mAction(arg1, arg2, arg3)) {
       mRegistered.Remove(listenerList[i]);
       mFreeListen.Push(listener);
       listenerList.RemoveAt(i);
      }
     }
     else {
      listenerList.RemoveAt(i);
     }
    }
    if(listenerList.Count == 0) {
     mRegisteredEvents.Remove(eventName);
    }
   }
  }
  
  class Listen {
   public int        mID;
   public Func<object,object,object,bool> mAction;
  }
  
  class Dispatched {
   public Dispatched Set(string eventName, object arg1=null, object arg2=null, object arg3=null) {
    mEventName = eventName;
    mArg1 = arg1;
    mArg2 = arg2;
    mArg3 = arg3;
    return this;
   }
   public string mEventName;
   public object mArg1, mArg2, mArg3;
  }
  
  Dictionary<string,List<int>>  mRegisteredEvents = new Dictionary<string, List<int>>();
  Dictionary<int,Listen>    mRegistered = new Dictionary<int, Listen>();
  Stack<Listen>      mFreeListen = new Stack<Listen>();
  Stack<Dispatched>     mFreeDispatch = new Stack<Dispatched>();
  Queue<Dispatched>     mDispatched = new Queue<Dispatched>();
  int         mNextListenID = 4711;
 }
}

接下来我会在最后一讲也就是设计六中,给大家说一下如何去使用。

时间: 2024-08-29 19:17:00

U3D架构系列之- FSM有限状态机设计五的相关文章

U3d架构系列之-FSM有限状态机设计一

我们在游戏开发中经常面临架构设计问题,在蛮牛问答里面也有好多朋友问关于架构方面的问题,在这里我就将一些经常使用的游戏开发方面的知识跟大家介绍 一下, 一是给大家提供一个设计思路,在此基础上可以举一反三,二是大家可以通过这个平台共同学习.闲话不多说了,切入正题,FSM有限状态机,在游戏开发中如何使用?那些模块的设计需要它?接下来我们就分析一下游戏: 比如我们的玩家自身的状态切换,Idle,walk,attack等等,这些都属于状态的切换,可以用有限状态机:还有比如玩家去完任务:领取任务,杀怪,交易

U3D架构系列之- FSM有限状态机设计四

接下来,我们继续我们的FSM有限状态机的设计,在设计三中我们实现了FSState这个类,我们继续实现FSEvent事件处理类.在FSEvent类里面我们声明了FiniteStateMachine里面定义的委托函数.代码如下: protected FiniteStateMachine.EnterState mEnterDelegate; protected FiniteStateMachine.PushState mPushDelegate; protected FiniteStateMachin

U3D架构系列之- FSM有限状态机设计六(总结篇)

由于最近一直赶项目进度,没时间写,昨晚终于项目终于完成了,空闲下来,做一个总结.在这一篇中主要是把前五章一起总结一下,以及通过举例演示如何使用?有限状态机在游戏中使用的地方非常多,比如我们界面之间的切换,角色的状态切换等等.所以非常值得大家去学习一下,接下来我们主要实现的功能,为了表达清楚,我通过图例给大家说明一下: 给大家解析一下,程序运行首先进入主菜单,里面有三个按钮,开始游戏,音量,退出游戏.先从第一个说起,如果是开始游戏,它会进入到下一个界面游戏界面,游戏界面有个返回主菜单功能.二者可以

U3D架构系列之- FSM有限状态机设计三

在设计二中,我们实现了有限状态机管理类,接下来,我们实现FSState这个类,这里类主要是状态的基本操作以及事件触发.在这里我们定义了在FiniteStateMachine类里声明的三个委托.在FSState里面使用的代码如下: protected FiniteStateMachine.EnterState mEnterDelegate; protected FiniteStateMachine.PushState mPushDelegate; protected FiniteStateMach

朱晔的互联网架构实践心得S1E9:架构评审一百问和设计文档五要素

朱晔的互联网架构实践心得S1E9:架构评审一百问和设计文档五要素 [下载文本PDF进行阅读] 本文我会来说说我认为架构评审中应该看的一些点,以及我写设计文档的一些心得.助你在架构评审中过五关斩六将,助你写出能让人收藏点赞的设计文档. 技术架构评审 架构评审或技术方案评审的价值在于集众人的力量大家一起来分析看看方案里是否有坑,方案上线后是否会遇到不可逾越的重大技术问题,提前尽可能把一些事情先考虑到提出质疑其实对项目的健康发展有很大的好处.很多公司都有架构评审委员会都有架构评审的流程,做业务的兄弟要

大型网站架构系列:消息队列(二)

本文是大型网站架构系列:消息队列(二),主要分享JMS消息服务,常用消息中间件(Active MQ,Rabbit MQ,Zero MQ,Kafka).[第二篇的内容大部分为网络资源的整理和汇总,供大家学习总结使用,最后有文章来源] 本次分享大纲 消息队列概述(见第一篇:大型网站架构系列:分布式消息队列(一)) 消息队列应用场景(见第一篇:大型网站架构系列:分布式消息队列(一)) 消息中间件示例(见第一篇:大型网站架构系列:分布式消息队列(一)) JMS消息服务 常用消息队列 参考(推荐)资料 本

大型网站架构系列:20本技术书籍推荐

学习是技术人员成长的基础,本次分享20本技术方面的书籍,这些书不是每一本都是经典,但是每一本都有其特点.以下20本大部分本人都看过,因此推荐给大家.(本次推荐的20本只是一个参考,比如像Head First,Java编程思想等经典书籍是大家都知道,因此不在推荐之列) 本次分享大纲 大型网站架构系列 分布式系统系列 BAT技术文学系列 架构设计系列 本次分享总结 一.大型网站架构系列 第一本:<大型网站技术架构:核心原理与案例分析> 这是本算是国内大型网站架构的经典之作,由阿里人李智慧创作,听名

大型网站架构系列:消息队列(二) (转)

本文是大型网站架构系列:消息队列(二),主要分享JMS消息服务,常用消息中间件(Active MQ,Rabbit MQ,Zero MQ,Kafka).[第二篇的内容大部分为网络资源的整理和汇总,供大家学习总结使用,最后有文章来源] 本次分享大纲 消息队列概述(见第一篇:大型网站架构系列:分布式消息队列(一)) 消息队列应用场景(见第一篇:大型网站架构系列:分布式消息队列(一)) 消息中间件示例(见第一篇:大型网站架构系列:分布式消息队列(一)) JMS消息服务 常用消息队列 参考(推荐)资料 本

【转载】大型网站架构系列20本书

[转载]http://www.cnblogs.com/chy2055/p/5181352.html 学习是技术人员成长的基础,本次分享20本技术方面的书籍,这些书不是每一本都是经典,但是每一本都有其特点.以下20本大部分本人都看过,因此推荐给大家.(本次推荐的20本只是一个参考,比如像Head First,Java编程思想等经典书籍是大家都知道,因此不在推荐之列) 本次分享大纲 大型网站架构系列 分布式系统系列 BAT技术文学系列 架构设计系列 本次分享总结 一.大型网站架构系列 第一本:<大型