Gamedev Framework (gf)
0.3.0
A C++11 framework for 2D games
|
In any game, you need to pass data around multiple parts of the code. The first choice is to make direct function calls. The main drawback of this approach is the tight coupling between the caller and the callee. The second choice is to use the observer pattern.
The purpose of gf::MessageManager is to provide a class that implements the observer pattern.
In this section, we will see how to defined and use messages in your game.
A message is just a structure with your own fields. In gf, a message must derive from gf::Message and define a static unique type.
This piece of code defines a message HeroPosition
with a single field: position
. The type of the message is "HeroPosition"_id
that is transformed at compile time in an integer of type gf::Id
.
To send a message, you need a gf::MessageManager. Here, we suppose we have a global variable called messageManager
of this type (see also Safe singletons).
Then, you only have to call gf::MessageManager::sendMessage() with an instance of your message.
To receive a message, you have to register a message handler in the message manager. A message handler is a function that will be called when a message of a given type is sent. This function can be a free function, or a member function. gf::MessageManager provides a shortcut for this last (very comon) case.
gf::MessageManager passes messages synchronously. This means that the message is sent immediately to handlers. An advantage is that there is no need for an allocation, the message can be put on the stack. A drawback is that care must be taken to avoid message loops. If handlers do not send messages, then the drawback disappears.
Each message handler receives an handler id when it is registered. This handler id can then be used to remove the handler directly through the gf::MessageManager::removeHandler() method.
The other method to remove a handler is to return gf::MessageStatus::Die at the end of the handler.
A common error is to register an handler as a method of an object and to delete this object without removing the handler. As a consequence, the message manager will try to call the handler and that will result in an error as the object does not exist anymore. This type of error can be very hard to find because the effect of the error is often indirect.
A good way to prevent this type of error for short life objects is to keep the handler ids and to remove the handlers in the destructor of the class.