patrick
patrick

Reputation: 9742

How do I setup a callback for every frame of a CCAction?

I want to do:

id action = [CCScaleTo actionWithDuration:0.5 scaleX:self.Xposition scaleY:1];
id ease   = [CCEaseInOut actionWithAction:action rate:4];

[someObject[i] runAction:ease];

But I want to be able to hook into each frame of the action to do some stuff... I am wondering if there is any way to accomplish this other than creating an update method on someObject? I am trying to avoid doing that because it's a CCSprite, and I don't currently have an object wrapper for it.. It literally is just defined as something like CCSprite *someObject[4] in the header... So I just wondered if there is any way to specify a per-frame callback in the context of runAction?

Upvotes: 0

Views: 1639

Answers (2)

CodeSmile
CodeSmile

Reputation: 64477

Blocks to the rescue!!! :)

id action = [CCScaleTo actionWithDuration:0.5 scaleX:self.Xposition scaleY:1];
id ease   = [CCEaseInOut actionWithAction:action rate:4];
id call = [CCCallBlockN actionWithBlock:^(CCNode* node) {
    // node is the sprite, you may have to cast it:
    CCSprite* someSprite = (CCSprite*)node;

    // do whatever you need to do with sprite here…
    someSprite.opacity = CCRANDOM_0_1() * 255;
}];
id sequence = [CCSequence actions:action, ease, call, nil];

[someObject[i] runAction:sequence];

Alternatively you can simply use the someObject[i] array as well and possibly even access the other sprites:

id action = [CCScaleTo actionWithDuration:0.5 scaleX:self.Xposition scaleY:1];
id ease   = [CCEaseInOut actionWithAction:action rate:4];
id call = [CCCallBlock actionWithBlock:^{
    CCSprite* someSprite = someObject[i];
    CCSprite* firstSprite = someObject[0];

    // do whatever you need to do with sprite here…
}];
id sequence = [CCSequence actions:action, ease, call, nil];

[someObject[i] runAction:sequence];

Upvotes: 1

Ben Trengrove
Ben Trengrove

Reputation: 8729

There is no native way to do this.

If this is what you really want to do rather than using an update method you could create a class similar to how the Ease actions work. Taking another action as a parameter and overriding update to modify its behavior.

For example if you called it CCCallBackAction it would be created as follows:

id action = [CCScaleTo actionWithDuration:0.5 scaleX:self.Xposition scaleY:1];
id ease   = [CCEaseInOut actionWithAction:action rate:4];
id callback = [CCCallBackAction actionWithAction:ease target:self selector:@selector(callback:)];

[someObject[i] runAction:callback];

In CCCallBackAction you would override update

- (void)update:(ccTime)dt
{
     [target performSelector:SEL];
     [other update:dt];
}

Note to avoid misunderstanding: CCCallBackAction is not a cocos2d class, it is hypothetical in this example

Upvotes: 1

Related Questions