WAYNETS.ORG

Game and Program

游戏引擎:事件系统

作者:

发表于

Context Polling System Post-Processing Renderer

事件

事件是游戏与玩家沟通的桥梁,对于服务于游戏的引擎而言,它需要根据情况判断来自输入设备产生的不同事件,比如:键盘按键事件,鼠标移动事件。

具体事件类别枚举:每一个事件子类都应属于以下某一个具体事件。

enum class EventType
{
	None = 0,
	WindowClose, WindowResize, WindowFocus, WindowLostFocus, WindowMoved,
	AppTick, AppUpdate, AppRender,
	KeyPressed, KeyReleased, KeyTyped,
	MouseButtonPressed, MouseButtonReleased, MouseMoved, MouseScrolled
};

除此之外,我们还定义了可用于组合的事件分类枚举,它使用位掩码来支持多个类别组合,比如:EventCategoryKeyboard = 1 << 2 = 4,用于快速按位比较。

enum EventCategory
{
	None = 0,
	EventCategoryApplication = BIT(0),
	EventCategoryInput       = BIT(1),
	EventCategoryKeyboard    = BIT(2),
	EventCategoryMouse       = BIT(3),
	EventCategoryMouseButton = BIT(4)
};

Event基类:

class Event
{
	friend class EventDispatcher;
public:
	virtual EventType GetEventType() const = 0;  
	virtual const char* GetName() const = 0;	   
	virtual int GetCategoryFlags() const = 0;	    
	virtual std::string ToString() const { return GetName(); } 

	inline bool IsInCategory(EventCategory category)
	{
		return GetCategoryFlags() & category;
	}
	
	bool Handled = false;
};

事件分发器

有了具体的事件类后,为了将它安全、优雅地转换成真正的类型,并交给相应的处理逻辑,我们需要引入事件分发器。

一个事件分发器应该实现以下功能:

  1. 检查传入的 Event 实例是否是某个具体类型(比如 KeyPressedEvent

2. 如果是,就交给你提供的处理函数来处理它

3. 设置事件的 Handled 标志位,防止重复处理

事件分发器代码:

class EventDispatcher
{
	template<typename T>
	using EventFn = std::function<bool(T&)>;
public:
	EventDispatcher(Event& event) : m_Event(event) {}

	template<typename T>
	bool Dispatch(EventFn<T> func)
	{
		if (m_Event.GetEventType() == T::GetStaticType())
		{
			m_Event.Handled = func(*(T*)&m_Event);
			return true;
		}
		return false;
	}
private:
	Event& m_Event;
};

Read Next:


Leave a comment