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);
}
Make sense, thanks, Riq.