组件-实体-系统 (ECS \CES)测试代码 C# DEMO

测试包含6个文件

委托:存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。若委托指明了参数类型,则委托可以被引用与任何符合该参数类型的方法

枚举类型:用来储存事件索引。对应在基类组件中的储存位置。

基类组件:提供储存容器,能够获取或设置自己的拥有者,能够注册事件,注册就是将事件对象储存在容器中。能够处理事件请求。

事件类:自定义的类,模拟现实动作。储存数据

组件类:继承自基类组件类,自定义处理事件请求

实例基类:包含用来储存组件的容器,接收到事件后,向每个组件发送事件请求,若组件已注册事件,则处理该事件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    /*
     事件定义枚举。
         */
    public enum EventDefines
    {
        Event_01 = 0,
        Event_02,
        Event_03,
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp2
{
    class Event //事件类
    {
        public int EventID = -1; //出事ID为 -1
        public ArrayList EventArgs = new ArrayList(); //事件参数列

        public void PushUserData<T>(T data)  //添加用户参数方法,参数为泛型
        {
            EventArgs.Add(data);
        }

        public T GetUserData<T>(int index)   //获得用户参数方法,参数为索引
        {
            if (index >= EventArgs.Count)  //如果索引出界,返回错误信息
            {
                Console.Write("GetUserData Error!");
                return default(T);
            }
            return (T)EventArgs[index];    //返回对应索引的数据。
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp2
{
    class ComponentBase //组件基类,所有组件都会继承此类
    {
        protected delegate void EventHandleFunction(Event evt);//事件委托

        private EntityBase Owner = null;
        // 事件映射表
        private Dictionary<int, EventHandleFunction> EventHandlerMap = new Dictionary<int, EventHandleFunction>();  //储存事件委托的字典。

        public virtual bool OnEvent(Event evt) //接受到事件请求,首先判断事件是否已经注册,即存在于容器之中,若存在,则对委托函数赋值,并经过判断后使用委托吃力请求
        {
            EventHandleFunction function = null;
            if (EventHandlerMap.TryGetValue(evt.EventID, out function) == false)
            {
                return false;
            }

            if (function == null)
                return false;

            function(evt);
            return true;
        }

        public virtual void OnAttachToEntity(EntityBase ety)
        {
            Owner = ety;
        }

        public virtual void OnDetachFromEntity(EntityBase ety)
        {
            Owner = null;
        }

        // 注册事件处理函数,同一事件注册两次,则后面的覆盖前面的
        protected void RegisterEvent(int eventID, EventHandleFunction handlerFunc)
        {
            if (EventHandlerMap.ContainsKey(eventID))
                EventHandlerMap.Remove(eventID);
            EventHandlerMap.Add(eventID, handlerFunc);
        }

        protected void UnregiterEvent(int eventID)
        {
            if (EventHandlerMap.ContainsKey(eventID))
                EventHandlerMap.Remove(eventID);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class TestComponent : ComponentBase
    {

        //制定拥有自己的实例,并注册事件
        public override void OnAttachToEntity(EntityBase ety)
        {
            base.OnAttachToEntity(ety);

            // 注册事件响应函数
            RegisterEvent((int)EventDefines.Event_01, DealEvent01);
            RegisterEvent((int)EventDefines.Event_03, DealEvent03);
        }

        public override void OnDetachFromEntity(EntityBase ety)
        {
            base.OnDetachFromEntity(ety);
        }

        private void DealEvent01(Event evt)
        {
            string evtData = evt.GetUserData<string>(0);
            Console.WriteLine("TestComponent Handle Event: ID = " + evt.EventID.ToString());
            Console.WriteLine("TestComponent Handle Event: Data = " + evtData);
        }

        private void DealEvent03(Event evt)
        {
            float evtData = evt.GetUserData<float>(0);
            Console.WriteLine("TestComponent Handle Event: ID = " + evt.EventID.ToString());
            Console.WriteLine("TestComponent Handle Event: Data = " + evtData);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApp2
{
    class EntityBase
    {
        // 组件列表,未实现RTTI,故用string做索引
        // 如果有RTTI,可以直接存储List<ComponentBase>,并且大多是这么做的
        // 字典,用来储存组建信息。
        Dictionary<string, ComponentBase> ComponentArray = new Dictionary<string, ComponentBase>();

        // 通过此函数将消息分发给各个Component,各个Component各自处理此消息
        // 通过DisptachEvetn,每个Compoent都会收到此消息,但是否处理此消息,由各组件自己决定
        public virtual bool DispatchEvent(Event evt)
        {
            bool bHandled = false; //处理标记 false
            foreach (ComponentBase comp in ComponentArray.Values) //迭代字典中的组件
            {
                bool ret = comp.OnEvent(evt);
                bHandled = (bHandled || ret);
            }
            if (bHandled == false)
                Console.WriteLine("Receive an unhandled event: id = " + evt.EventID.ToString());

            return bHandled;
        }

        public bool AddComponent(string compName, ComponentBase compObject)
        {
            if (compObject == null)
            {
                Console.Write("AddComponent Failed, Component.Name=" + compName);
                return false;
            }

            ComponentArray.Add(compName, compObject);
            compObject.OnAttachToEntity(this);
            OnComponentAttached(compObject);
            return true;
        }

        public bool RemoveComponent(string compName)
        {
            if (!ComponentArray.ContainsKey(compName))
            {
                Console.Write("RemoveComponent Failed, Component.Name=" + compName);
                return false;
            }

            ComponentArray[compName].OnDetachFromEntity(this);
            OnComponentDetached(ComponentArray[compName]);
            ComponentArray.Remove(compName);
            return true;
        }
        //附属方法
        public virtual void OnComponentAttached(ComponentBase compObject)
        {
        }

        public virtual void OnComponentDetached(ComponentBase compObject)
        {
        }

    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            // 构造一个EntityBase对象
            EntityBase ety = new EntityBase();
            // 添加TestComponent组件,可以移到EntityBase的继承类的构造函数中
            TestComponent testComp = new TestComponent();
            ety.AddComponent("TestComponent", testComp);

            // 发送消息Event_01
            Event evt1 = new Event();
            evt1.EventID = (int)EventDefines.Event_01;
            evt1.PushUserData<string>("SomeData For Event01");
            ety.DispatchEvent(evt1);

            // 发送消息Event_02
            Event evt2 = new Event();
            evt2.EventID = (int)EventDefines.Event_02;
            evt2.PushUserData<string>("SomeData For Event02");
            ety.DispatchEvent(evt2);

            // 发送消息Event_03
            Event evt3 = new Event();
            evt3.EventID = (int)EventDefines.Event_03;
            evt3.PushUserData<float>(0.123f);
            ety.DispatchEvent(evt3);

            Console.Read();

        }
    }
}

运行结果:

TestComponent Handle Event: ID = 0
TestComponent Handle Event: Data = SomeData For Event01
Receive an unhandled event: id = 1
TestComponent Handle Event: ID = 2
TestComponent Handle Event: Data = 0.123

测试组件没有注册Event_02,没有结果。

猜你喜欢

转载自blog.csdn.net/Da___Vinci/article/details/81587638
今日推荐