Since Basic key frame animations, implicit casts and some other aspect, I've continued to make gradual improvements to my game prototype which now includes an event manager and some cool retro sounds.
The event manager concept is simple, when we get a game event from the keyboard, we send the event to the event manager and it forwards a copy of that event to each subscriber of that event. What I did was have my actors subscribe to a particular event during initialization and then use the event manager to decouple these actors from the keyboard handling logic. In fact, this allows any object to do things based on events without knowing where the events came from.
The concept is routinely used in event-based programming that I've used before in C# and Java particularly around GUI design and having read about it in GCC4 a while back, I thought I'd have a stab at implementing it. As you might recall this was part of the architecture detailed in A simple game engine architecture.
The basis of the event system as described above is simple:
#pragma once
#include <vector>
#include <memory>
#include "Event.h"
#include "EventSubscriber.h"
class EventManager
{
public:
EventManager();
void RegisterEvent(std::shared_ptr<Event> evt);
void SubscribeToEvent(EventType type, EventSubscriber* you);
~EventManager();
void ProcessEvents();
private:
std::vector<std::shared_ptr<Event>> events;
std::map<EventType, std::vector<EventSubscriber*>> event_subscribers;
};
The system maintains a list of events and who is subscribed to them. When its asked to process the events as part of the update() phase of the game loop, it marries up subscribers with events. Simple:
#include "EventManager.h"
#include <vector>
#include "EventSubscriber.h"
#include <iostream>
EventManager::EventManager()
{
}
void EventManager::RegisterEvent(std::shared_ptr<Event> evt)
{
std::cout << "Registering event." << std::endl;
events.push_back(evt);
}
void EventManager::SubscribeToEvent(EventType type, EventSubscriber* you)
{
std::cout << "Subscribed to event" << std::endl;
event_subscribers[type].push_back(you);
}
EventManager::~EventManager(){}
void EventManager::ProcessEvents()
{
// go through all the events and call all ther subscribers telling them about the event
if(events.size() != 0)
{
std::cout << "Processing events..." << std::endl;
}
for(std::vector<std::shared_ptr<Event>>::iterator it = events.begin(); it != events.end();it++)
{
std::shared_ptr<Event> evt = *it;
std::vector<EventSubscriber*> subscribers = event_subscribers[evt->m_eventType];
for(EventSubscriber* subscriber : subscribers)
{
subscriber->ProcessEvent(evt);
}
}
events.clear();
}
It works quite well and though I haven't tried it for more than one type of event (I've just designed a PositionChangedEvent type), it looks promising. I'm not too worried about performance at this point. I've implemented a concept of an event subscriber which details how objects that would like to subscribe to events should structure themselves so that the event manager can contact them with the events that they subscribed to.
This means basically that my actors are Event Subscribers, capable of processing events passed to them by the event manager. This is how my Ball class deals with the PositionChangedEvent:
#include "Ball.h"
#include "Events.h"
#include <memory>
#include "Event.h"
#include <iostream>
void Ball::ProcessEvent(std::shared_ptr<Event> evt)
{
// Handle PositionChangeEvents
if(evt->m_eventType == PositionChangeEventType)
{
std::shared_ptr<PositionChangeEvent> cpe = std::dynamic_pointer_cast<PositionChangeEvent>(evt);
if(cpe->m_direction == Up){
MoveUp();
std::cout << "Move up event processed" << std::endl;
}
if(cpe->m_direction == Down){
MoveDown();
std::cout << "Move down event processed" << std::endl;
}
if(cpe->m_direction == Left){
MoveLeft();
std::cout << "Move left event processed" << std::endl;
}
if(cpe->m_direction == Right){
MoveRight();
std::cout << "Move right event processed" << std::endl;
}
}
}
Ball::~Ball()
{
}
This is hardly a complete solution but more a work in progress, a game prototype if you will.
If you want you can have a look at how I've defined my events, which is also quite rudimentary.
In other news, I attended my course on C programming recently and it was like my Event Manager, a little rudimentary however that doesn't mean it wasn't useful: I know exactly where I need to be, come Oct time.
Started learning about Digital Forensics which I've found it quite interesting, and my last couple of runs in Four close run-ins have been really good and I've enjoyed them tremendously. I read a paper about Digital triage today. It is here if you want to read it:
The sum of today’s activity so far(I need to get to bed earlier): A survey of digital forensic investigator decision processes and measurement of decisions based on enhanced preview - ScienceDirect https://t.co/dHT3gQEjNT
— Stuart Mathews (@stumathews) May 5, 2019