Skip to content

ECS Event Handlers

Thomaltarix edited this page Nov 3, 2024 · 2 revisions

What's an Event Handler?

An Event Handler is a piece of logic that can process an event with access to more modules than simple systems. Event Handlers operates on entities that have the required components. For example:

  • A SwitchSceneEventHandler might process the "SwitchScene" event. So, the handler will catch the scene path in the values of the event, and will change the scene thanks to the scene manager.
  • A ConnectServer might process the "ConnectServer" event. So, the handler will catch the needed settings from the event values, and use the network to connect to the server.

How to Write One

In our game engine, developers and the community can create custom systems and components. Components are written in C++.

Tutorial

If you haven’t already read the ECS Events section, please take a moment to review it.

In this tutorial, we'll create a SwitchScene event handler. This handler will change the current scene by the needed one.

Let's Implement It

First, create a SwitchSceneHandler.hpp file. Include the following files:

#include "AEventHandler.hpp"
#include "../Error/AError.hpp"
  • AEventHandler: Simply an abstract to avoid duplicating the same code for each handler.
  • ISystem: the interface class for system. To create a new system, it must inherit from this interface.

Now, let's create our system class. It must inherit from the AEventHandler class.

class SwitchSceneHandler : public AEventHandler {

    public:

        SwitchSceneHandler(); // Constructor

        ~SwitchSceneHandler() = default; // Default destructor
};

Then, ISystem has a single method to override, it's the method to get the function system:

class SwitchSceneHandler : public AEventHandler {

    public:

        bool processEvent(std::shared_ptr<IEvent> event, std::shared_ptr<SceneManager::ISceneManager> sceneManager, std::shared_ptr<ABINetwork::INetworkUnit> networkUnit, std::shared_ptr<IGraphic> graphicLib) override;
};

This method takes the Event, the SceneManager, the NetworkUnit and the GraphicLib. This allows us many access to modules of the application unlike simple systems. Now, let's implement the method

SwitchSceneHandler::SwitchSceneHandler(std::string eventType)
    : AEventHandler("SwitchScene") {}

bool SwitchSceneHandler::processEvent(std::shared_ptr<IEvent> event,
                                      std::shared_ptr<SceneManager::ISceneManager> sceneManager,
                                      std::shared_ptr<ABINetwork::INetworkUnit> networkUnit,
                                      std::shared_ptr<IGraphic> graphicLib)
{
    try {
        // Get the scene path from the event values
        std::string sceneName = std::any_cast<std::string>(event->getValues()[0]);
        std::pair<std::size_t, std::string> scenePair = std::make_pair(0, sceneName);
        // Using the scene manager, change the scene to the wanted one
        sceneManager->changeScene(scenePair);
    } catch (const std::exception &e) {
        throw SwitchSceneHandlerError("Error while processing the event: " + std::string(e.what()));
    }
    return true;
}

Here we are ! We have our first event Handler !

But that's not the end. How will the game Engine use our event handler ?

For that, we must create an entry point. When the handler will be loaded in the game Engine, it will call this entry point to get the Event Handler class.

For that, create a cpp file named SwitchSceneHandler.cpp put this on it:

#include "SwitchSceneHandler.hpp"

extern "C" {
    EXPORT_SYMBOL ISystem* loadSystemInstance() {
        return new SwitchSceneHandler();
    }
}

This function will return our Event Handler class previously created, the EXPORT_SYMBOL is a macro use to make windows able to open .dll files.

Compile your Handler with this command in your terminal:

g++ -fPIC -shared -o theNameOfYourEventHandler.so yourFile.cpp

Replace theNameOfYourEventHandler by the name you want to give to your Event Handler file, and yourFile.cpp by the SwitchSceneHandler.cpp.

Finally, place your file .so in the Game/Engine/ folder. The system will be automatically loaded when the game Engine will be running.