有没有更好的方法来制作EventManager

时间:2017-04-09 10:15:36

标签: c++ sfml

我为我的EventManager制作了一些代码,它工作正常,但问题是,我用很多复制粘贴创建了它,我想每次你开始复制粘贴一个几行,你的代码设计得很糟糕。

所以,在EventManager上做了很多复制粘贴后,我认为现在是时候找出是否有另一种方法来制作它(可能有,也可能更好)。

我所取得的成就是当一个事件发生时(window.pollEvent(event)),它会调用onEvent(sf::Event, sf::RenderWindow*)类的EventManager方法,对于我需要监听的每个事件,我都会调用所有听众的实例。

这是班级:

public:
    void registerKeyPressed(std::shared_ptr<KeyPressedEventListener> listener);
    void registerWindowResized(std::shared_ptr<WindowResizedEventListener> listener);
    void registerWindowFrameUpdate(std::shared_ptr<WindowFrameUpdateEventListener> listener);
private:
    std::vector<std::shared_ptr<KeyPressedEventListener>> m_keyPressedListeners;
    std::vector<std::shared_ptr<WindowResizedEventListener>> m_windowResizedListeners;
    std::vector<std::shared_ptr<WindowFrameUpdateEventListener>> m_windowFrameUpdateListeners;

所以,问题是,只有3个听众有很多代码(我目前有6个,但是因为代码总是相似的,所以显示它们没有用。)

我的问题是我希望一个类能够一次监听一个,两个或更多事件,所以我的所有监听器都有一个不同的函数,当事件发生时调用它。例如,这三个侦听器具有onKeypressed(sf::Event);onWindowResized(sf::Event, sf::RenderWindow* window);onFrameUpdate(sf::RenderWindow* window);功能。这是我发现使这段代码有效的唯一方法。

它确实有效,但我想做些更好的事情,因为每个事件都有很多代码:

void EventManager::onEvent(sf::Event event, sf::RenderWindow* window) { // The window argument is used further, but it's not useful to show it here as the code is quite the same
    switch (event.type) {
    case sf::Event::Resized:
        for (unsigned int i = 0; i < m_windowResizedListeners.size(); i++) {
            if (m_windowResizedListeners.at(i)->onWindowResized(event)) break; // The events return a bool value : True if the loop has to stop (for an error, for example), false otherwise. I always return false unless an error happen, but it's in case I need to stop it.
        }
        break;
    }
}
void EventManager::registerWindowResized(std::shared_ptr<WindowResizedEventListener> listener) {
    m_windowResizedListeners.push_back(listener);
}

我必须为每个事件复制此代码。如果有错误,你就会明白纠正它会有很多工作,所以我希望你能帮我找到更好的方法来实现它。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您可以使用公共类:

class EventHandler{

public:

    virtual void handle(sf::RenderWindow &window) = 0;
};

class EventManager {

public:
    void registerKeyPressed(std::shared_ptr<EventHandler> listener);
    void registerWindowResized(std::shared_ptr<EventHandler> listener);
    void registerWindowFrameUpdate(std::shared_ptr<EventHandler> listener);
private:
    std::vector<std::shared_ptr<EventHandler>> m_keyPressedListeners;
    std::vector<std::shared_ptr<EventHandler>> m_windowResizedListeners;
    std::vector<std::shared_ptr<EventHandler>> m_windowFrameUpdateListeners;
}

您现在可以在类中定义一个地图,键是事件类型,值是他的侦听器矢量。

    std::map<int,std::vector<std::shared_ptr<EventHandler>>*> eventType;
}

//...

EventManager::EventManager(){
    eventType[sf::EventType::Resized] = &m_windowResizedListeners;
    eventType[sf::EventType::KeyPressed] = &m_keyPressedListeners;

    //Keep going...
}

现在,onEvent函数非常简单:

void EventManager::onEvent(sf::Event event, sf::RenderWindow* window) {
    std::vector<std::shared_ptr<EventHandler>>* ptr = eventType[event.type];
    for (int i = 0;i < ptr->size();i++)
        (*ptr)[i]->handle(window);
}

我们举一个例子:

class SettingsSaver : public EventHandler{

   public:
       void handle(sf::RenderWindow &window) override {
           std::cout << "I am saving the state in the hardrive before of exit" << std::endl;
       }
}

class MoveHero : public EventHandler{

   public:
       void handle(sf::RenderWindow &window) override {
           std::cout << "I am moving the character" << std::endl;
       }
}

// Main

std::shared_ptr<EventHandler> settingsSaver(new SettingsSaver);
std::shared_ptr<EventHandler> moveHero(new MoveHero);

EventManager manager;
manager.registerWindowClosed(settingsSaver);
manager.registerKeyPressed(moveHero);