In Objective C calling a selector after a given delay is a piece of cake as this is built in NSObject. Everyone who has touched the iPhone SDK has one time or another come across the following code:

[self performSelector:@selector(doSomething) withObject:nil afterDelay:0.5f];

If you haven’t got a clue what that does, it calls the doSomething method on the current object after a 0.5 second delay. Useful when you want to perform an action after the user does something or to hide a notification after a while.

It’s not that particularly complicated to do the same thing in C++, but you need to make use of some of Cocos2D-x features such as CCSequence, CCDelayTime and CCCallFunc.

First, let’s look at the code:

  1. // set up the time delay
  2. CCDelayTime *delayAction = CCDelayTime::actionWithDuration(0.5f);
  3. // perform the selector call
  4. CCCallFunc *callSelectorAction = CCCallFunc::actionWithTarget(this, 
  5.                                                               callfunc_selector(HelloWorld::doSomething));
  6. // run the action
  7. this->runAction(CCSequence::actions(delayAction,
  8.                                     callSelectorAction,
  9.                                     NULL));

First, you need to set up the time delay using a CCDelayTime action. Simple enough, you send the duration of the intended delay as an argument to the method.

Then, you need to set up the selector call action. The first argument you are going to send is the object to perform the action on, the second one is a pointer to the function from that object. After the time delay action expires, the doSomething method will be called on the object represented by this. In my case, this is the scene layer.

If you are wondering, callfunc_selector is a macro that simply casts the pointer of the argument it receives to a SEL_CallFunc. This is what this baby looks like:

#define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR)

Finally, we call runAction on the current scene. The runAction method takes as a parameter a CCSequence object. This CCSequence object allows you to chain together multiple sequential actions.

You must separate your action by a comma, and ALWAYS close the list of actions with a NULL. Failure to do so will crash your app as there is no way for CCSequence to know when to stop executing actions. This is especially true for Android, and especially weird on iOS where it doesn’t crash, but what you need to keep in mind is to always close an enumeration of actions with a NULL.

Hope this helps you Cocos2D-x noobs 😛

Share this article

12 thoughts on “Performing a selector after a delay in Cocos2D-x

  • September 25, 2011 at 4:43 am
    Permalink

    This is exactly what I was looking for, this is the only blog or place that I have seen this information for cocos2d-x. Thanks alot!!

    Reply
  • May 14, 2012 at 12:55 pm
    Permalink

    I meet some problem when I use ur method.
    It’s just only a C++ problem.
    I have a class A inherits from CCObject, a class B inherits from both A and CCNode, I use ur code in B, “callfunc_selector” have a error when i compile it.

    Ambiguous conversion from pointer to member of derived class ‘B’ to pointer to member of base class ‘cocos2d::CCObject’:
    class B -> class A -> class cocos2d::CCObject
    class B -> class cocos2d::CCNode -> class cocos2d::CCObject

    how should I to deal with it.

    Reply
  • May 25, 2012 at 3:45 pm
    Permalink

    This is exact match of my problem.
    Thanks !!

    Reply
  • May 26, 2012 at 9:57 pm
    Permalink

    Very elegant, thank you!

    Reply
  • October 18, 2012 at 4:41 am
    Permalink

    the problem with this it cannot be stopped. i tried like this:
    this->runAction(CCSequence::create(CCDelayTime::create(1.0f),CCCallFunc::create(this,callfunc_selector(TGGestureRecognizer::pressAndHold)),NULL))->setTag(100);

    and i stop it.
    this->stopActionByTag(100);

    The pressAndHold is still get called.

    Reply
  • November 25, 2012 at 5:42 pm
    Permalink

    Some of the functions are deprecated..
    CCDelayTime::actionWithDuration
    CCCallFunc::actionWithTarget and
    CCSequence::actions

    I use the following code

    CCDelayTime *delayTime = CCDelayTime::create(0.5f);
    CCCallFunc *functionToCall = CCCallFunc::create(this,callfunc_selector(HelloWorld::doSomething);
    CCFiniteTimeAction *actionSequence = CCSequence::create(delayTime,functionToCall,NULL);
    this->runAction(actionSequence);
    </blockquote

    Reply
  • March 11, 2013 at 6:39 am
    Permalink

    Thanks for the snippet. Couldn’t find a good example of how to actually do this. Now I understand that the delay is just on of the actions in the sequence, no where else explained that.

    Reply
  • April 18, 2013 at 9:03 am
    Permalink

    action with target is deprecated
    what to use instead ?

    Reply
  • August 12, 2013 at 2:21 am
    Permalink

    Howdy, I
    believe your blog could be having browser compatibility issues.

    When I take a look at your site in Safari, it looks fine but when opening
    in IE, it has some overlapping issues.

    I simply wanted to give you
    a quick heads up! Aside from that, fantastic website!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Email
Print