Event Dispatcher is a mechanism for responding to events such as touching screen, keyboard events and custom events. You can get an event using Event Dispatcher. In addition, you can create Observer Pattern
in the design patterns using it. In this recipe, you will learn how to use Event Dispatcher and how to create Observer Pattern in Cocos2d-x.
Firstly, we will go through the details of Observer Pattern. Observer Pattern is a design pattern. When an event occurs, Observer notifies the event about the subjects that are registered in Observer. It is mainly used to implement distributed event handling. Observer Pattern is also a key part in the MVC architecture.
We will create a count up label per second in this recipe. When touching a screen, count up labels are created in this position, and then, count up per second using Observer Pattern.
Count
class that is extended Label
class as shown in the following code:Count.h class Count : public cocos2d::Label { private: int _count; void countUp(float dt); public: ~Count(); virtual bool init(); CREATE_FUNC(Count); }; Count.cpp Count::~Count() { this->getEventDispatcher()- >removeCustomEventListeners("TimeCount"); } bool Count::init() { if (!Label::init()) { return false; } _count = 0; this->setString("0"); this->setFontScale(2.0f); this->getEventDispatcher()- >addCustomEventListener("TimeCount", [=](EventCustom* event) { this->countUp(0); }); return true; } void Count::countUp(float dt) { _count++; this->setString(StringUtils::format("%d", _count)); }
HelloWorld::countUp
method per second using a scheduler as the following code in HelloWorld.cpp
:bool HelloWorld::init() { if ( !Layer::init() ) { return false; } auto listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(_swallowsTouches); listener->onTouchBegan = C_CALLBACK_2(HelloWorld::onTouchBegan, this); this->getEventDispatcher()- >addEventListenerWithSceneGraphPriority(listener, this); this->schedule(schedule_selector(HelloWorld::countUp), 1.0f); return true; } bool HelloWorld::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event) { auto countLabel = Count::create(); this->addChild(countLabel); countLabel->setPosition(touch->getLocation()); return true; } void HelloWorld::countUp(float dt) { this->getEventDispatcher()- >dispatchCustomEvent("TimeCount"); }
TimeCount
. If TimeCount
event occurred, then the Count::countUp
method is called.this->getEventDispatcher()- >addCustomEventListener("TimeCount", [=](EventCustom* event) { this->countUp(0); });
EventDispatcher
when the instance of the Count
class is removed. If you forget to do that, then the zombie
instance will be called from EventDispatcher
when the event occurs and your game will crash.this->getEventDispatcher()- >removeCustomEventListeners("TimeCount");
HelloWorld.cpp
, call the HelloWorld::countUp
method using the scheduler. The HelloWorld::countUp
method calls the custom event called TimeOut
.this->getEventDispatcher()- >dispatchCustomEvent("TimeCount");
And then, EventDispatcher
will notify this event to the listed subjects. In this case, the Count::countUp
method is called.
void Count::countUp(float dt){ _count++; this->setString(StringUtils::format("%d", _count)); }
Using EventDispatcher
, labels count up at the same time. If you use Scheduler instead of EventDispatcher
, you will notice something different.
Change the Count::init
method as shown in the following code:
bool Count::init() { if (!Label::init()) { return false; } _count = 0; this->setString("0"); this->setFontScale(2.0f); this->schedule(schedule_selector(Count::countUp), 1.0f); return true; }
In this code, use a scheduler by calling the Count::countUp
method per second. You can see that the labels are not counting up at the same time in this way. Each label is counting up per second, however not at the same time. Using Observer Pattern, a lot of subjects can be called at the same time.
52.14.138.41