It's been a while since I wanted to add a event system to cocos2d, and these days I've been working with Unity3D, which mostly relays on the event system to send information across all classes so I started working on it for cocos2d.
For those who don't know how a messaging system works, just imaging that you are creating a IA that for your FPS, and you want to notify all surrounding IA troops that the enemy base camp is under attack, then you'll have to perform this tasks:
- Create the "UnderAttack" event.
- Then you'll subscribe, in your IA enemies, to the message/event "UnderAttack" you want to listen.
- create the listener for these event in which you'll have the code to react under this event.
- then you'll send the "UnderAttack" event from your IA enemy that has discovered you.
Cocoa has it's on system, which is called Notification System, that works very well, but you have to write quite a lot of code to get it working so I've written a wrapper to simplify everything.
Messaging system
There are bassically three actions you can do on a messaging system as described before, subscribe to the event, unsubscribe of that event, and send messages.
Subscribe
The wrapper for that action is:
//Subscribes to aMessage event.And what you'll have to write in your code to subscribe the events:
#define AMSubscribe(aSelector, aMessage, aObject) \
[[NSNotificationCenter defaultCenter] addObserver:(self) selector:(aSelector) name:(aMessage) object:(aObject)]
Create the event, (writting the event listener):
-(void)eventHandler: (NSNotification *) notificationAnd then subscribe to the event with:
{
// senderObject contains the pointer to the sendMessage passed object. can be nil.
id senderObject = [notification object];
NSLog(@"%@ event triggered", self);
}
// custom onEnterI've added the AMSubscribe inside the cocos2d onEnter call, just to make sure it is called before any possible message is sent and thus lost, but you can add it everywhere you actually need it.
-(void) onEnter
{
[super onEnter];
//Here we should register the event listener
AMSubscribe(@selector(eventHandler:), @"theTestEvent", nil);
}
Things you should remember:
- the selector name is the listener function
- @"theTestEvent" is the name of the event and how you'll call it.
- you don't actually need the third parameter, so left it as nil. It's used if you only want to listen to this object messages.
- the listener function has to be in the same class subscribing to the event.
The function you should call is defined as:
//Unsubscribe aMessage event for caller object.And this is how you should use it:
#define AMUnsubscribeMessage (aMessage) \
[[NSNotificationCenter defaultCenter] removeObserver:(self) forKeyPath:(aMessage)]
//Unsubscribes all events for caller object.
#define AMUnsubscribe \
[[NSNotificationCenter defaultCenter] removeObserver:(self)]
// custom onExitAs before, I've implemented it on the onExit function to make sure it is removed when the scene is moved, but you'll be able to add it wherever you want.
-(void) onExit
{
[super onExit];
//Here we should unregister the event listener
AMUnsubscribe;
}
NOTE: Just remember to Unsubscribe to all the events before releasing the object or it will leak.
Send Messages
You'll send the messages with:
// send the message aMessage with aObject dataAnd you it as:
#define AMSendMessage(aMessage, aObject) \
[[NSNotificationCenter defaultCenter] postNotificationName:(aMessage) object:(aObject)]
-(void) menuCallbackSEND: (id) senderThis code is extracted from the sample code below. Which sends a theTestEvent message with the NSNumber 10 as data.
{
AMSendMessage(@"theTestEvent", [NSNumber numberWithInt:10]);
}
Implementation
The implementation of the system is as easy as adding the "MessagingSystem.h" class to your project and calling the functions as described before.
Download
You can download a sample project with everything on it.
It consist of a clean project, just to be as familiar as possible, with the library added.
It consist on the HelloWorld scene subscribed to the event and another CCNode class with a label also registered to the event.
that will run as:
And after pressing the SEND button:
The file | MessagingSystem.h
The sample project | Test project
If anyone has any suggestion or question leave it in the comments. I'll be glad to answer.
Thank you for reading.