我有一个小问题,关于事件系统,不太知道该问题该放在哪里,如果发错地方了,抱歉。
现在我正在实现实体组件系统:渲染,一切都在完美地进行。我需要实施移动控制,以便它可以像以前一样工作。在我的运动代码像这样工作之前:我有一个按钮数组,可以处理每个按钮(我使用了按钮的 Windows 代码),我的运动工作非常顺利。
现在,当我实现了事件系统时,我有一个小型消息系统,我可以在其中订阅事件并发出事件。我在 win32 WndProc 函数中发出按键向上和向下消息。现在的问题是:按下按钮时,动作不流畅;就好像按钮不断地被间歇性地按下一样,导致我的动作变得不稳定。
基本上,现在我有这个系统(可以正常工作):
typedef std::list<std::unique_ptr<base_event_handler>> handler_list;
struct event_bus
{
std::unordered_map<std::type_index, std::unique_ptr<handler_list>> EventList;
std::vector<std::function<void()>> EventsQueue;
void Reset()
{
EventList.clear();
}
template<typename owner, typename event_type>
void Subscribe(owner* Owner, void (owner::*CallbackFunction)(event_type& E))
{
if(!EventList[std::type_index(typeid(event_type))].get())
{
EventList[std::type_index(typeid(event_type))] = std::make_unique<handler_list>();
}
std::unique_ptr<event_handler<owner, event_type>> Subscriber(new event_handler<owner, event_type>(Owner, CallbackFunction));
EventList[std::type_index(typeid(event_type))]->push_back(std::move(Subscriber));
}
template<typename event_type, typename... args>
void Emit(args&&... Args)
{
handler_list* Handlers = EventList[std::type_index(typeid(event_type))].get();
if(Handlers)
{
event_type Event(std::forward<args>(Args)...);
for(auto It = Handlers->begin(); It != Handlers->end(); It++)
{
base_event_handler* Handler = It->get();
EventsQueue.push_back([=](){Handler->Execute(const_cast<event_type&>(Event));});
}
}
}
void DispatchEvents()
{
for (auto& EventFunction : EventsQueue)
{
EventFunction();
}
EventsQueue.clear();
}
};
问题是我从调度循环中发出消息,我想这很糟糕,但我不知道哪里会更好:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
u16 VkCode = LOWORD(wParam);
u16 Flags = HIWORD(lParam);
u16 RepeatCount = LOWORD(lParam);
bool IsPressed = (Message == WM_KEYDOWN || Message == WM_SYSKEYDOWN);
bool IsReleased = (Message & KF_UP) == KF_UP;
bool IsExtended = (Flags & KF_EXTENDED) == KF_EXTENDED;
bool WasDown = (Flags & KF_REPEAT ) == KF_REPEAT;
switch(VkCode)
{
case EC_MENU:
case EC_SHIFT:
case EC_CONTROL:
{
VkCode = LOWORD(MapVirtualKeyW(LOBYTE(Flags), MAPVK_VSC_TO_VK_EX));
} break;
}
Buttons[VkCode] = {WasDown, IsPressed, RepeatCount};
if(IsPressed) EventsDispatcher.Emit<key_down_event>(VkCode, RepeatCount);
if(IsReleased) EventsDispatcher.Emit<key_up_event>(VkCode, RepeatCount);
} break;
抱歉,如果这个问题有点愚蠢,提前致谢
这是我对静态多态解决方案的含义的快速概述
#include <vector>
#include <functional>
#include <type_traits>
#include <string>
#include <iostream>
// very basic (thread unsafe) event registration class
template<typename... args_t>
class event_source_t
{
public:
template<typename fn_t>
void register_callback(fn_t fn)
{
m_callbacks.push_back(fn);
}
void raise_event(args_t&&... args)
{
for(const auto& callback : m_callbacks)
{
callback(std::forward<args_t>(args)...);
}
}
private:
std::vector<std::function<void (args_t...)>> m_callbacks;
};
// use the event infrastructur in a class
class class_with_events_t
{
public:
void register_on_hello(std::function<void(const std::string&)> fn)
{
m_hello_events.register_callback(fn);
}
void say_hello(const std::string& name)
{
m_hello_events.raise_event(name);
}
private:
event_source_t<const std::string&> m_hello_events;
};
int main()
{
class_with_events_t class_with_events;
class_with_events.register_on_hello([](const std::string& name) { std::cout << name << "\n"; });
class_with_events.say_hello("Arheus");
return 0;
}