尝试在我的应用程序中实现更好的事件系统

问题描述 投票:0回答:1

我有一个小问题,关于事件系统,不太知道该问题该放在哪里,如果发错地方了,抱歉。

现在我正在实现实体组件系统:渲染,一切都在完美地进行。我需要实施移动控制,以便它可以像以前一样工作。在我的运动代码像这样工作之前:我有一个按钮数组,可以处理每个按钮(我使用了按钮的 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;

抱歉,如果这个问题有点愚蠢,提前致谢

c++ winapi
1个回答
0
投票

这是我对静态多态解决方案的含义的快速概述

#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;
}
© www.soinside.com 2019 - 2024. All rights reserved.