组件-实体-系统 (ECS \CES)测试代码 C# DEMO
测试包含6个文件委托:存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。若委托指明了参数类型,则委托可以被引用与任何符合该参数类型的方法枚举类型:用来储存事件索引。对应在基类组件中的储存位置。基类组件:提供储存容器,能够获取或设置自己的拥有者,能够注册事件,注册就是将事件对象储存在容器中。能够处理事件请求。事件类:自定义的类,模拟现实动作。储存数据组件类:继承自基类...
·
测试包含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,没有结果。
更多推荐
已为社区贡献3条内容
所有评论(0)