I asked about this ages ago, and was helped to solve the idea, thought I'd share an action.
Basically, if you need to mask out a sprite, you can use this action. I combine it with a move action, to make things "pop out" from behind of walls or floors
e.g.
id jumpOut = [MoveBy actionWithDuration:1 position:ccp(-90,0)];
id mask = [MaskTo actionWithDuration:1 rect:CGRectMake(0, 0, 0, 140)];
id maskBack = [MaskTo actionWithDuration:1 rect:CGRectMake(0, 0, 85, 140)]; // I didn't write reverse yet..
id repeatMove = [RepeatForever actionWithAction:
[Sequence actions: jumpOut, [jumpOut reverse],nil] ];
id repeatMask = [RepeatForever actionWithAction: [Sequence actions: maskBack, mask,nil] ];
[ghost runAction:repeatMove ];
here's the code:
MaskTo.h
@interface MaskTo : IntervalAction <NSCopying>
{
CGRect endRect;
CGRect startRect;
CGRect delta;
}
/** creates the action */
+(id) actionWithDuration:(ccTime)duration rect:(CGRect)rect;
/** initializes the action */
-(id) initWithDuration:(ccTime)duration rect:(CGRect)rect;
@end
MaskTo.m
@implementation MaskTo
+(id) actionWithDuration: (ccTime) t rect: (CGRect) r{
return [[[self alloc] initWithDuration:t rect:r ] autorelease];
}
-(id) initWithDuration: (ccTime) t rect: (CGRect) r{
if( !(self=[super initWithDuration: t]) )
return nil;
endRect = r;
return self;
}
-(id) copyWithZone: (NSZone*) zone{
Action *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] rect: endRect];
return copy;
}
-(void) start{
[super start];
startRect = [(AtlasSprite*)target textureRect];
CGPoint endXY = ccp(endRect.origin.x, endRect.origin.y);
CGPoint endWH = ccp(endRect.size.width, endRect.size.height);
CGPoint startXY = ccp(startRect.origin.x, startRect.origin.y);
CGPoint startWH = ccp(startRect.size.width, startRect.size.height);
CGPoint deltaXY = ccpSub( endXY, startXY );
CGPoint deltaWH = ccpSub( endWH, startWH );
delta = CGRectMake(deltaXY.x, deltaXY.y, deltaWH.x, deltaWH.y);
}
-(void) update: (ccTime) t{
CGRect newTextureRect = CGRectMake(
(startRect.origin.x + delta.origin.x * t ), (startRect.origin.y + delta.origin.y * t ),
(startRect.size.width + delta.size.width * t ), (startRect.size.height + delta.size.height * t ) );
[(AtlasSprite*)target setTextureRect: newTextureRect];
}
@end