这个里面做的事情很简单
使用枚举对游戏中事件进行了分类
并有一个存储事件数据的结构体 AND 一个处理事件的接口
【Irrlicht 中枚举体和结构体的命名规范】
枚举类型命名以 'E' 打头,表示 Enum
枚举中每一个元素以 ‘E’ + 枚举体名下划线分割的每个单词首字母拼接 打头
比如枚举体 EEVENT_TYPE 中每一个元素都以 EET 开头
结构体类型命名以 'S' 打头, 表示 Struct
这些也是非常常用的命名规范
(但是 联合体union 好像没有遵循类似的规则)
【EEVENT_TYPE】
枚举了 Irrlicht 中的事件类型
Irrlicht 中事件分三种 : GUI事件 AND 鼠标输入事件 AND 键盘输入事件
enum EEVENT_TYPE
{
EET_GUI_EVENT = 0, // GUI 事件
EET_MOUSE_INPUT_EVENT, // 鼠标输入事件
EET_KEY_INPUT_EVENT // 键盘输入事件
};
【EMOUSE_INPUT_EVENT】
进一步枚举了鼠标输入事件中更具体的事件类型
这里枚举了七个最常用的鼠标事件类型
分别对应 "左键", "右键", "中键" 的 "按下", "抬起" 事件 AND 鼠标移动事件
enum EMOUSE_INPUT_EVENT
{
EMIE_LMOUSE_PRESSED_DOWN = 0, // 左键按下
EMIE_RMOUSE_PRESSED_DOWN, // 右键按下
EMIE_MMOUSE_PRESSED_DOWN, // 中键按下
EMIE_LMOUSE_LEFT_UP, // 中键抬起
EMIE_RMOUSE_LEFT_UP, // 右键按下
EMIE_MMOUSE_LEFT_UP, // 右键抬起
EMIE_MOUSE_MOVED // 鼠标移动
};
【EGUI_EVENT_TYPE】
枚举了GUI系统中用到的一些事件
具体的事件类型我已经在下面代码中添加好了注释
enum EGUI_EVENT_TYPE
{
EGET_ELEMENT_KEY_FOCUS_LOST = 0, // 键盘按键焦点丢失
EGET_ELEMENT_MOUSE_FOCUS_LOST, // 鼠标指针焦点丢失
EGET_ELEMENT_HOVERED, // 鼠标指针悬停
EGET_BUTTON_CLICKED, // 鼠标按键点击
EGET_SCROLL_BAR_CHANGED, // 滚动条改变
EGET_CHECKBOX_CHANGED, // 复选框状态改变
EGET_LISTBOX_CHANGED, // 列表框列表选项内容改变
EGET_LISTBOX_SELECTED_AGAIN, // 列表框中已经选中的选项被再次选中
};
这三个枚举将 Irrlicht 中的事件进行了枚举
后面的事件记录结构以及事件处理接口将根据它们对事件进行解析
其实这些事件定义本身是不够全面的
但是其中囊括的大都十分常用,而且也是容易扩充的,所以也足够了
【SEvent】
记录事件数据的结构体
因为具体的事件分为三类且是独立出现不会重合的
所以用 联合体并分别定义了记录三种事件信息的结构,可以减小存储空间
使用一个EEVENT_TYPE 记录事件类型
可以根据 EVENT_TYPE 判断要以union中的哪一个结构解析数据
struct SEvent
{
EEVENT_TYPE EventType;
union
{
struct // GUI事件数据
{
gui::IGUIElement* Caller; // 发送该事件的控件
gui::EGUI_EVENT_TYPE EventType; // 事件的类型
} GUIEvent;
struct // 鼠标输入数据
{
s32 X, Y; // 鼠标在事件发生时的坐标
EMOUSE_INPUT_EVENT Event; // 鼠标事件的类型
} MouseInput;
struct // 键盘输入数据
{
s32 Key; // 发生该事件的按键
bool PressedDown; // 只有按下和非按下两个状态, true - 按下事件, false - 抬起事件
} KeyInput;
};
};
【IEventReceiver】
接口以 ‘I’ 开头, 但是 C++ 标准关键字里没有 interface (接口)
所以使用一个 IEventReceiver 基类, 里面只有一个用来处理事件的纯虚函数
子类继承自 IEventReceiver 并实现 OnEvent 来处理事件
class IEventReceiver
{
public:
// 事件发生的时候被调用, 如果事件被成功处理则返回 true
virtual bool OnEvent(SEvent event) = 0;
};
这些就是 IEventReceiver 中对事件的定义以及记录和处理的方法
个人觉得 Irrlicht 中对文件的划分还是阔以的
(所有相关的内容放在一个文件里对读的人来说也是一种爱 ヘ(_ _ヘ) )
////////////////////////////////////////// 废话 buff 开始 //////////////////////////////////////////
我自己刚开始做小游戏的时候根本没有对事件进行这么清晰的定义
更多的时候只是做一个全局的消息分发者,然后发送消息,调用函数
但是后来渐渐发现,有一些事情处理起来的时候不禁叫人 "头皮发麻" 后 "呵呵一笑"
比如 使用消息分发队列来控制消息合并等行为
比如 有一个事件需要改变参数
比如 要增加或者删除一个事件类型
所以对事件系统进行良好的定义是很有必要的
////////////////////////////////////////// 废话 buff 结束 //////////////////////////////////////////
今天失恋了,发一张不开心的图片 (づ╥﹏╥)づ