auto sprite = Sprite::create("file.png");
layer1->addChild(sprite);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = some_functions;
listener->onTouchMoved = some_functions;
listener->onTouchEnded = some_functions;
listener->onTouchCancelled = some_functions;
// This event listener registeration is before the `sprite` is added into scene graph, that means before `onEnter`.
sprite->addEventListenerWithSceneGraphPriority(listener, sprite);
// If in some places, we remove sprite from its parent(layer1), and add it into another layer (layer2)
sprite->retain();
sprite->removeFromParent();
layer2->addChild(sprite); // Here we re-add the sprite to layer2
sprite->release();
In Node::onExit
, we remove the event listener from EventDispatcher
.
void Node::onExit()
{
...
removeAllEventListeners();
}
Since the touch event registeration is right after the sprite was created rather than sprite's onEnter
,
sprite will never get response of touch if without registering touch listener again.
Solution 1: Clone the listener after it's created and when sprite is added to a new layer, we invoke adding touch listener again.
auto listener = EventListenerTouchOneByOne::create();
...
// Clone the listener
auto cloneListener = listener->clone();
// If in some places, we remove sprite from its parent(layer1), and add it into another layer (layer2)
sprite->retain();
sprite->removeFromParent();
layer2->addChild(sprite); // Here we re-add the sprite to layer2
sprite->addEventListenerWithSceneGraphPriority(cloneListener, sprite);
sprite->release();
void Node::onEnter()
{
...
if (this->onEnterHook)
{
this->onEnterHook();
}
}
auto sprite = Sprite::create("file.png");
layer1->addChild(sprite);
// Hook onEnter
sprite->onEnterHook = [this](){
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = some_functions;
listener->onTouchMoved = some_functions;
listener->onTouchEnded = some_functions;
listener->onTouchCancelled = some_functions;
// This event listener registeration is before the `sprite` is added into scene graph, that means before `onEnter`.
sprite->addEventListenerWithSceneGraphPriority(listener, sprite);
};
-
No need to save the listener pointer and add the listener by
clone
. When the second timesprite
is added toscene graph
, theonEnterHook
will be called. And a new event listener will be added toEventDispatcher
again. -
No need to subclass node and override
onEnter
method. Just assignNode::onEnterHook
.
Example:
void runHelloWorldScene()
{
auto scene = Scene::create();
auto layer = Layer::create();
scene->addChild(layer);
layer->onEnterHook = [&](){
// do_something_to_init_the_layer
auto sp = Sprite::create();
layer->addChild(sp);
};
Director::getInstance()->replaceScene(scene);
}
It should be handled like
update
or actions.onExit
pauses the updates, actions. It doesn't remove it.onEnter
resumes the updates, actions. It does't create new ones.It should be the same for events.
eg: