Reputation: 51
With Cocos2D V3 after action has completed on a sprite I need to update data contained in a structure. How can I pass a data structure address to a selector that executes after my sprite action has completed? Any help much appreciated.
Upvotes: 2
Views: 2162
Reputation: 21
Although i suggest to move on and use blocks, Here is my ARC friendly version of CCActionCallFuncND. Works with many kinds of data, including primitives, and any objective C class, at most NSArray's and such... Any comment to improve it to be even better is wellcome!
// CCActionCallFuncND.h
#import "CCActionInstant.h"
typedef void (*CC_CALLBACK_ND)(id, SEL, id, void *);
@interface CCActionCallFuncND : CCActionCallFunc<NSCopying>
+(id) actionWithTarget:(id)t selector:(SEL)s data:(void*)d;
-(id) initWithTarget:(id)t selector:(SEL)s data:(void*)d;
@end
// CCActionCallFuncND.m
#import <malloc/malloc.h>
#import "CCActionCallFuncND.h"
#import <objc/runtime.h>
@interface CCActionCallFuncND ()
@property(strong, nonatomic, readwrite)id myObject;
@property(strong, nonatomic, readwrite)NSValue *myValue;
@property(nonatomic, readwrite)CC_CALLBACK_ND callbackND;
@end
@implementation CCActionCallFuncND
+(id)actionWithTarget:(id)t selector:(SEL)s data:(void*)d
{
return [[self alloc] initWithTarget:t selector:s data:d];
}
-(id)initWithTarget:(id)t selector:(SEL)s data:(void*)d
{
if((self=[super initWithTarget:t selector:s]))
{
self.myValue=[NSValue valueWithPointer:d];
self.myObject=nil;
bool bIsOfClass=false;
int classesNumber=objc_getClassList(NULL, 0);
Class *classesList = (Class*)malloc(classesNumber*sizeof(Class));
classesNumber = objc_getClassList(classesList, classesNumber);
for(int i=0; i<classesNumber; i++)
{
if(classesList[i]==*((Class *)d))
{
bIsOfClass=true;
break;
}
}
free(classesList);
if(bIsOfClass)
{
self.myValue=nil;
self.myObject=(__bridge id)d;
}
self.callbackND=(CC_CALLBACK_ND)[t methodForSelector:s];
}
return self;
}
-(id)copyWithZone:(NSZone*)zone
{
CCActionInstant *copy = [[[self class] allocWithZone: zone]
initWithTarget:_targetCallback selector:_selector data:[self.myValue pointerValue]];
return copy;
}
-(void)execute
{
void *dat=self.myValue?(void*)[self.myValue pointerValue]:(__bridge void*)self.myObject;
self.callbackND(_targetCallback, _selector, _target, dat);
}
@end
Upvotes: 1
Reputation: 3012
You would use a CCActionCallBlock
or a CCActionCallFunc
. Whichever is appropriate for your use case.
Here is an code example of a block being called after a move to action.
CCActionMoveBy* moveToSomeAwesomePlace = [CCActionMoveBy actionWithDuration:0.1f position:CGPointZero];
CCActionCallBlock *actionAfterMoving = [CCActionCallBlock actionWithBlock:^{
self.someProperty = 42;
}];
CCActionSequence *movingSequeceAndOtherStuffAfter = [CCActionSequence actionWithArray:@[moveToSomeAwesomePlace, actionAfterMoving]];
[self runAction:movingSequeceAndOtherStuffAfter];
And here is an example using a CCActionCallFunc
that executes a selector after the move action.
CCActionMoveBy* moveToSomeAwesomePlace = [CCActionMoveBy actionWithDuration:0.1f position:CGPointZero];
CCActionCallFunc *callAfterMoving = [CCActionCallFunc actionWithTarget:self selector:@selector(someMethod)];
CCActionSequence *movingSequeceAndOtherStuffAfter = [CCActionSequence actionWithArray:@[moveToSomeAwesomePlace, actionAfterMoving]];
[self runAction:movingSequeceAndOtherStuffAfter];
Upvotes: 4