weird behavior on getting a callback after an action (animation) sequence finishes

weird behavior on getting a callback after an action (animation) sequence finishes
0.0 0


I have a Tank class that contains a sprite (this seemed like a good design pattern so I can have custom game logic in my classes, have the classes keep physics and sprites in sync, etc). My master GameLayer creates a Tank and then lets the Tank initialize itself. Later, the GameLayer gets an update call, and tells the tank to update itself. In the Tank’s update it is currently just playing some sprite animation over and over (the tank “rumbles” up and down for a few frames and I want to play that animation while it’s just sitting there). So it’s an animation that needs to run for 4 frames, and then repeat until its time for the tank to do something else.

So in the Tank class, I’ve setup an action to play a few frames animating my sprite. After setting up my animation, the call looks like this:
_tankRumble = CCSequence::create( CCAnimate::create(animation), CCCallFuncN::create(sprite, callfuncN_selector(Tank::tankRumbleDone)),NULL); _tankRumble->retain();

then on my update loop, I just look at some internal state variable (isAnimating) for the Tank, and if it’s not animating, I make a call to run the animating sequence using _tankRumble from above, and set the state variable to tell me it’s animating so I don’t call it every frame. And then eventually my tankRumbleDone() method will get called back so I can reset my state variable to tell me it’s time to start the animation again on the next loop.

The problem is that the callback seems to go into a black hole. It doesn’t seem to call my Tank object in memory, so the isAnimating state doesn’t work properly. It animates once, and then kaput. Now, if I make my Tank class inherit from CCNode, and then change the call above from the selector to be “this” instead of “sprite” then things work fine. I’ve also tried passing it the layer that contains the tank, and that doesn’t work either. either the layer can have all the logic to do this stuff and it’s fine, or the Tank class needs to inherit from some node (CCNode, CCObject, etc).

why is that? I’m clearly missing something fundamental.


So, as far as I understand, you are trying to call Tank::tankRumbleDone in sprite object, which is not, I assume, the instance of the Tank class?


Correct. The Tank class contains a sprite (which is a CCSprite). The Tank is not a sprite - in my code above, the sprite is the Cocos2dx object that is getting the animation applied to it, and the method of is the method where the logic gets performed.

So I guess what I was missing is that the CCCallFuncN must take a CCObject , and the callback function you pass should be a method of that object, and the cocos engine will then call back that method on that specific object instance. Is that correct? I read the notes in the .h file and this wasn’t obvious to me (I’m still fairly new, but the documentation has been tough to get through).


Actually, this is not related to cocos2d-x or any other lib, it’s a matter of pure C++. You just can’t call the method which does not belong to the class. In your case you are trying to call tankRumbleDone which belongs to the Tank class, not to CCSprite.


thanks for the fast responses. It’s been about 10 yrs since I’ve coded anything in C++. I was probably confusing this with something closer to eventing (and just assuming cocos was handling all the internals to make it work). I need to spend some time to brush up and learn more about the language - fighting the language and trying to learn a full API makes for frustrating going.