Creating Observer Pattern

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.

Getting ready

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.

Getting ready

How to do it...

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.

  1. Create 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));
    }
  2. Next, when touching a screen, this label will be created at the touching position and will call the 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"); }
  3. After building and running this project, when you touch the screen, it will create a count up label at the touching position, and then you will see that the labels are counting up per second at the same time.

How it works...

  1. Add the custom event called TimeCount. If TimeCount event occurred, then the Count::countUp method is called.
    this->getEventDispatcher()- >addCustomEventListener("TimeCount", [=](EventCustom* event) {
        this->countUp(0);
    });
  2. Don't forget that you need to remove the custom event from 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");
  3. In 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));
    }

There's more…

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.138.41