事件
事件是游戏与玩家沟通的桥梁,对于服务于游戏的引擎而言,它需要根据情况判断来自输入设备产生的不同事件,比如:键盘按键事件,鼠标移动事件。
具体事件类别枚举:每一个事件子类都应属于以下某一个具体事件。
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;
};
事件分发器
有了具体的事件类后,为了将它安全、优雅地转换成真正的类型,并交给相应的处理逻辑,我们需要引入事件分发器。
一个事件分发器应该实现以下功能:
- 检查传入的
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;
};

Leave a comment