Reputation: 475
In my scene I have a vector with multiple custom sprites. When I tap on one of them, I want an action to be fired on another element on the scene, can be another sprite in the vector, or another node. I have been researching the best way to do this, but I'm not quite sure how to implement it. The options are:
Add a touch listener to the scene, and verify if it was tapped inside the bounds of the sprite with rect. containsPoint(point)
. And after that, I have to get the sprite that was tapped to do the action I want. For me, it doesn't seems very clean to do it this way. And if two sprites are overlaped, I have to verify if the sprite is behind or in the front in order to retrieve the desired sprite. I followed this example: Touch Event example
Add a touch listener in the subclass of the sprite (my custom sprite). And add onTouchBegan
and onTouchEnded
inside it. But this way, I don't know how to modify an attribute of another sprite, or another element in the scene (Is it possible to use Delegates like Objective-C does?). I followed this example: Subclass Sprite Example
My main problem is that I don't understand very well how to make a node interact with another node in the scene. I have seen a lot of tutorials, but in all of them, when you interact with a node, it only changes its attributes, not other nodes' attributes.
Thanks in advance.
Upvotes: 1
Views: 2360
Reputation: 44
I shall propose "EventCustom" way :)
You can add in your touchBegan / touchEnded methods (wherever you put them... you got the point...) additional code for passing an EventCusto to the _eventDispatcher and get it announced to the world ;)
EventCustom *e = new EventCustom("MyAwesomeEvent");
e->setUserData(ptrMyFantasticData); //This function takes a void pointer. cheers :)
_eventDispatcher->dispatchEvent(e);
You may subclass the EventCustom class but that is hardly necessary. You can always hang an object to it with setUserData().
Now the objects which need to react to the event can listen to it by
_myCustomListener = EventListenerCustom::create(
"MyAwesomeEvent",
CC_CALLBACK_1(
ListeningClass::onMyAwesomeEvent,
this
)
);
_eventDispatcher->addEventListenerWithXXXXXPriority(_myCustomListener, XXX);
//ScreenGraphPriority / FixedPriority depends on situation. Either should work.
It's always a good practice to remove your listeners when you go off, so somewhere, perhaps in onExit(), where you removed touch listeners remove this listener too, as
_eventDispatcher->removeEventListener(_myCustomListener);
Going a bit off the track, a clarification:
CC_CALLBACK_X are a bit tricky names. The X indicates the no. of args the target function will get. Here, event dispatcher will pass 1 arg i.e. ptr to object of EventCustom you handed it, so we use CC_CALLBACK_1. The next arg - here "this" - is the object on which the method will be invoked.
In short, we may say that this callback is going to result into a function call this->onMyAwesomeEvent(e);
For CC_CALLBACK_2 onwards, we can specify additional args, 3rd arg onwards.
Coming back to the issue at hand, ListeningClass::onMyAwesomeEvent will look something like
void ListeningClass::onMyAwesomeEvent(EventCustom *e)
{
MyFantasticData *d = (MyFantasticData *) e->getUserData();
CCLOG("[ListeningClass::onMyAwesomeEvent] %d", d->getMyPreciousInt());
}
Hope it helps :)
Upvotes: 1
Reputation: 1
With the second option you list above. To make a node interact with another node in the scene you can add touch callback function to your custom sprite object like that: https://github.com/Longpc/RTS/tree/master/Classes/base/dialogBase
and in main scene you can define function to handle this callback. So you can do every thing to unit in you scene
Upvotes: 0
Reputation: 116
Set your elements tags or names with setTag
and setName
. Then if element x is touched, get them with getChildByTag
or getChildByName
and do what you need to do.
Upvotes: 0