Keep track of sprites in a vector

This might be a more general C++ question, but is there a way I can apply an event listener to a vector of objects? I don’t need to listen for input, just for the size of the vector. In my game, I have populations of various animals, and I want a real-time count of them. It’s a little tricky because the number display is on the parent layer, and the vector is on a child layer.

Thanks!

You could use custom events.
http://cocos2d-x.org/docs/programmers-guide/8/index.html#creating-a-custom-event

Otherwise you could access the parent directly.

auto parent = static_cast<ParentClass*>(this->getParent());
parent->setCount(objVector.size());

@stevetranby Can you tell me benefits of using custom events?
I mean to fire custom event we have to call dispatchEvent, instead of that cant we just call simple method directly?
Or am i missing anything?
Due to this confusion i never tried to use custom events.
Thanks.

Custom events are like messages so the main benefit is decoupling and not having to have a direct link to the callee (tag, pointer, index, etc). Often I’ve seen message passing used for HUD <–> Game communication. However, in games you want to execute as fast as possible, so often the optimization is to get a direct link and use it.

Some entity component systems use message passing and the custom events could be used to implement it.

We use it sparingly and mostly with any cross-system communication or when updating HUD backing state.

Custom events fire immediately so their only cost is any function call indirections. Even something as direct as this->getParent() technically may go through one function call indirection (depending on optimizations I suppose) and not be much more costly.

Some people may also just think around messages better in some circumstances.

It’s really just another tool in the toolbox.

@stevetranby what do you think about creating your custom listeners in the background on game startup, registering them all with the dispatcher and calling them whenever needed?

@slackmoehrle You can create them wherever you want provided the listener exists at any point when you want a message to succeed. If you have a need for messages outside/beyond a given scene then app startup works. If you have events to capture at any point during game play from load to scene change then attach them in your scene startup. Or if you have a HUD layer you can attach HUD events in the init or you can register in onEnter, and deregister in onExit.

I’m no expert, but I would usually put my listeners nearby the state which is affected. So, for example, a HUD state update I would think to put the listener in the HUD class (Layer/Node).

Whereas the Unit class may want to know about friendly or enemy Units that have died, or are in danger and are requesting help. I would put this listener inside the Unit or Unit Manager/System.

I wouldn’t personally put all my listeners code in the same place. Say the master class GameManager that exists during the entirety of the app from launch to exit. I prefer code locality for productivity.

Edit: granted if an event could be called at any point, then I would probably put the listener in the AppDelegate.

void AppDelegate::setupEventListeners()
{
    auto dispatcher = Director::getInstance()->getEventDispatcher();
    dispatcher->addCustomEventListener(GLView::EVENT_WINDOW_RESIZED, [](EventCustom* event) {
        dinfo("<<< WINDOW RESIZED! >>> ");
        STDevice::get()->refreshDesignScaleFactors();
    });
    dispatcher->addCustomEventListener(GLView::EVENT_WINDOW_FOCUSED, [](EventCustom* event) {
        dinfo("<<< WINDOW FOCUSED! >>> ");
    });
    dispatcher->addCustomEventListener(GLView::EVENT_WINDOW_UNFOCUSED, [](EventCustom* event) {
        dinfo("<<< WINDOW BLURRED! >>> ");
    });
}
1 Like

I don’t use 'em currently in my cocos2d-X code - but with similar functionality in other languages (in addition to those mentioned already) is that there can be multiple listeners that you don’t need to be aware of as the broadcaster.

So, say you raise a custom event when the Baddy dies. And you subscribe to it in the HUD in order to update the score, show the number of remaining baddies, whatever.

You could have done that by using a global reference to the HUD, or making the HUD a singleton etc. and all would be fine.

Later you decide that, when a baddy dies, you want your player to do a short ‘woohoo’ animation.

with events, let the player listen for the message and do what it needs to - no change required to your Baddy class.

With the global reference/singleton model you’d have to change the Baddy class to call the method on the Player directly.

1 Like