So, here’s the first update, way behind schedule.

I’ve written a simple event system just to get started. It consists of a listener pool and message pool. The messages also contain a void pointer, so they can basically contain any information I’d like. It’s a rather dirty system all together, but it works for now, and at least I have something I can work on now. For simplicity, I’ve not written any header files for this, but I’ll separate the declarations and definitions later on.

Enums are supposed to be bad for this, but this will probably not be a huge engine I’m writing, so I’ll let it slide for now. Basically, every message and listener attached to the system contains a messageType field, and in order for a listener to receive a message, both the messageType fields must match in the listener and message.

typedef enum _EVENT_MESSAGES{
	EVENT_NULL = 0,
	EVENT_BASIC
} __EVENT_MESSAGES;

I don’t really have to use an enum for this, as it’s basically just ID’s, but it’s neat to have a name on the event types.

Carrying on, we have the base message. All other messages will be derived from this, and it consists of the messageType field and a void pointer, as mentioned earlier. The void pointer can be anything, thus the sender and listeners have to agree on the data set being used. Eventually, I’ll add serializing functions, etc, to the message so that it can be made ready to be sent through the pipes of the internets.

class CEventMessage{
public:
	void* data;	// Pointer to a data set. The listener should know what this is.
	unsigned long int messageType;
};

Next we have the base listener class. It also contains a messageType field, and a virtual function that the derived listeners will overwrite to add their functionality. The return value of the handleMessage function tells the manager if the listener ate the message, and removes the message from the pool accordingly. This allows for a listener to decide it it wants to use the message or not, and if other listeners should be allowed to use it further. Of course, the latter isn’t too useful if it becomes a “first come first served” scenario.

class CEventBaseListener{
public:
	unsigned long int messageType;	// Listen for this message.
	virtual bool handleMessage(CEventMessage* eventMsg) = 0;
};

And finally, we have the event manager itself. The manager contains two pools, one for incoming messages, and one for attached listeners. The pools are simply an array of pointers and an array of bools used to tell which spots in the pointer array are free. A listener have to be attached to the manager to receive messages, and messages have to go through the same process. You can as often as you’d like broadcast the messages stored in the pool, which means you don’t have to wait until all messages have been added to the pool before you broadcast.

Currently there is only one major problem with this; If you add a message of a type there is no listeners for, the message will never be removed. This can and will easily be solved by adding a “best-before” time-stamp on the messages, I was just too lazy to add this for now.

class CEventManager{
public:
	CEventMessage		*eventMessages		[1024];
	bool			eventMessagePool	[1024];

	CEventBaseListener	*eventListeners		[1024];
	bool			eventListenerPool	[1024];

	CEventManager(){
		for(int i = 0; i < 1024; ++i){
			eventMessagePool[i] = eventListenerPool[i] = false;
		}
	}

	// Search for a free spot and add the listener
	int addListener(CEventBaseListener *listener){
		for(int i = 0; i < 1024; ++i){
			if(eventListenerPool){
				eventListeners[i] = listener;
				eventListenerPool[i] = true;
				return i;
			}
		}
		// Return -1 if none found
		return -1;
	}
	// Search for a free spot and add the message
	int addMessage(CEventMessage *message){
		for(int i = 0; i < 1024; ++i){
			if(eventMessagePool){
				eventMessages[i] = message;
				eventMessagePool[i] = true;
				return i;
			}
		}
		// Return -1 if none found
		return -1;
	}
	int broadcastMessages(){
		int handled = 0;
		// For all listeners
		for(int i = 0; i < 1024; ++i){
			// If listener is active
			if(!eventListenerPool[i])
				continue;
			// Loop through all messages
			for(int j = 0; j < 1024; ++j){
 				// Is message is active
				if(!eventMessagePool[j])
					continue;
				//If message types match
				if(eventListeners[i]->messageType == eventMessages[j]->messageType){
					if(eventListeners[i]->handleMessage(eventMessages[j])){
						handled++;
						//delete eventMessages[j];
						eventMessagePool[j] = false;
					}
				}
			}
		}
		return handled;
	}
};

 

 

Now that we have the basics done, it’s really easy to add messages. Here I’ve made a simple message and a data class to be sent to a listener:

// This data class is used by the basic message
class CBasicMessageData{
public:
	int i1;
	int i2;
	int dataValue;
	char array[15];
};

// This is a basic message
class CBasicMessage : public CEventMessage{
public:
	// Define what kind of message this is
	CBasicMessage(){
		messageType = EVENT_BASIC;
	}
};

// This is a basic listener
class CBasicEvent : public CEventBaseListener{
public:
	// Define what messages we're listening for
	CBasicEvent(){
		messageType = EVENT_BASIC;
	}
	bool handleMessage(CEventMessage* eventMsg){
		// We must trust the sender of this message used the correct data type
		CBasicMessageData *msgData = (CBasicMessageData*)eventMsg->data;
		printf("Handled a basic message with dataValue = %i\n", msgData->dataValue);
		// Eat the message
		return true;
	}
};

And putting it all to use:

int main(){

	// Create our event manager
	CEventManager msgManager;

	// Broadcast no messages to no listeners
	int handled = msgManager.broadcastMessages();
	if(!handled)
		printf("Success, no messages handled!\n");
	else
		printf("WTF: Some messages were handled!\n");

	CBasicMessage msg;		// Create our message
	CBasicMessageData msgData;	// Create the data class for our basic message
	msgData.dataValue = 15;		// Assign some arbitrary data
	msg.data = (void*)&msgData;	// Attach our data class as a void pointer
	CBasicEvent listener;		// Create our listener

	// Add message and listener to the manager
	msgManager.addListener(&listener);
	msgManager.addMessage(&msg);

	// Broadcast messages again
	handled = msgManager.broadcastMessages();
	if(handled)
		printf("Success, messages was handled!\n");
	else
		printf("WTF: No messages were handled!\n");

	return 1;
}

The above code should give this output:

Success, no messages handled!
Handled a basic message with dataValue = 15
Success, messages was handled!

 

The next thing that will be done on this project is to make engine class and initialization code, so that I can get some graphics displayed.

(All bugs in the code posted are mine)

Sorry, the comment form is closed at this time.