Cocos2D: Passing a CGPoint through CCCallFuncND

2019-06-09 08:14发布

问题:

What is the appropriate way to call a method with an action, and what should the method itself look like for passing a CGPoint parameter? I've tried to look up examples online without much luck, so I've been pretty much guessing.

What I have tried is this for calling it:

    CGPoint spriteCoord = saveStation.sprite.position;

    id a1=[CCMoveTo actionWithDuration:.4 position:ccp(saveStation.sprite.position.x,saveStation.sprite.position.y)];
    id actionSaveStationReaction = [CCCallFuncND actionWithTarget:self selector:@selector(saveStationReaction : data:) data:&spriteCoord];

    [hero.heroSprite runAction:[CCSequence actions:a1, actionSaveStationReaction, nil]];

And the method itself:

-(void) saveStationReaction:(id)sender data:(void *)data {

    CGPoint spriteCoord = (void *)data; //error: Invalid initializer 

    NSLog(@"spriteCoord x = %f", spriteCoord.x);
    NSLog(@"spriteCoord y = %f", spriteCoord.y);

}

回答1:

The proper way to send a CGPoint (or any non-id type like C structs) to a method that takes an id as parameter (any method that uses performSelector) is by wrapping it in an NSValue object:

NSValue* value = [NSValue valueWithBytes:&spriteCoord objCType:@encode(CGPoint)];

In the method that is being called you can retrieve the point from the NSValue object by casting the data pointer to NSValue* and calling getValue:

-(void) saveStationReaction:(id)sender data:(void *)data {

    CGPoint spriteCoord;
    [((NSValue*)data) getValue:&spriteCoord];

    NSLog(@"spriteCoord x = %f", spriteCoord.x);
    NSLog(@"spriteCoord y = %f", spriteCoord.y);

}


回答2:

GamingHorror's suggestion on wrapping the CGPoint in an NSValue is spot-on.

But there's a simpler way than using valueWithByte:objCType: method: valueWithCGPoint:, assuming you are coding for iOS and not MacOS.

NSValue *spriteCoordValue = [NSValue valueWithCGPoint:spriteCoord];
[CCCallFuncND actionWithTarget:self selector:@selector(saveStationReaction:data:) data:spriteCoordValue];

// and ..
-(void) saveStationReaction:(id)sender data:(void *)data {

    CGPoint spriteCoord = [(NSValue *)data CGPointValue]; 

    NSLog(@"spriteCoord x = %f", spriteCoord.x);
    NSLog(@"spriteCoord y = %f", spriteCoord.y);

}

NSValue can also deal with CGSize and CGRect using similar way.



回答3:

You can't typecast to a CGPoint with that syntax. Try....

CGPoint *spriteCoord = data;

CGFloat ptX = spriteCoord->x;
CGFloat ptY = spriteCoord->y;

I tried...

CGPoint* spriteCoord = (CGPoint)data;

which didn't work and I guess expectedly so. Try my first suggestion and see if that works for you. It did compile for me but I'm not sure how it will execute and that may depend on your particular situation.



回答4:

CGPoint is a struct, not an object, so you can't pass it directly to any of the CCCallFunc's. There are several ways of dealing with this, but the quickest converts the CGPoint to NSString using NSStringFromCGPoint, passing the string, then converting it back to a CGPoint using CGPointFromString.