Masking a Sprite: The Implementation
Open up HelloWorldLayer.m and add the following method right above init:
- (CCSprite *)maskedSpriteWithSprite:(CCSprite *)textureSprite maskSprite:(CCSprite *)maskSprite {
// 1
CCRenderTexture * rt = [CCRenderTexture renderTextureWithWidth:maskSprite.contentSizeInPixels.width height:maskSprite.contentSizeInPixels.height];
// 2
maskSprite.position = ccp(maskSprite.contentSize.width/2, maskSprite.contentSize.height/2);
textureSprite.position = ccp(textureSprite.contentSize.width/2, textureSprite.contentSize.height/2);
// 3
[maskSprite setBlendFunc:(ccBlendFunc){GL_ONE, GL_ZERO}];
[textureSprite setBlendFunc:(ccBlendFunc){GL_DST_ALPHA, GL_ZERO}];
// 4
[rt begin];
[maskSprite visit];
[textureSprite visit];
[rt end];
// 5
CCSprite *retval = [CCSprite spriteWithTexture:rt.sprite.texture];
retval.flipY = YES;
return retval;
}
Let’s go over this section by section.
- Create a CCRenderTexture with the same width/height as the mask sprite.
- Positions the mask sprite and texture sprite so their bottom left is at 0,0.
- Sets up the blend functions for each sprite as discussed earlier.
- Calls begin to start drawing into the CCRenderTexture, draws the mask and then the texture, and then calls end to finalize drawing.
- Creates a new sprite based on the CCRenderTexture’s sprite’s texture. Flips it along the y-axis because the texture is upside down.
After everything we discussed, makes sense no? Now let’s use it! Replace the area between BEGINTEMP and ENDTEMP with the following:
CCSprite * mask = [CCSprite spriteWithFile:@"CalendarMask.png"];
CCSprite * maskedCal = [self maskedSpriteWithSprite:cal maskSprite:mask];
maskedCal.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:maskedCal];
This uses our new function to mask the calendar sprite, and adds the masked version to the scene.
Compile and run, and now you should see a masked sprite with Cocos2D 1.0!
Drawbacks of the CCRenderTexture Method
For this simple little app this works fine, but there are some drawbacks to this method you might start to notice for more complicated apps:
-
Creates an additional texture in memory each time you apply a mask. Texture memory is very limited on the iPhone so you have to be very careful about how many textures you have in memory at once. This is fine if you only need to mask a few textures at a time, but what if you have to mask 100?
-
Takes time to draw. Drawing with CCRenderTexture is not cheap (especially as your textures get larger). If you are doing this frequently, you might notice a performance hit.
Like I mentioned earlier, there is no way that I know of to get around these drawbacks with OpenGL ES 1.0. With OpenGL ES 2.0 you can mask much more efficiently with a shader – but that’s a topic for another tutorial!
Where To Go From Here?
Here is a sample project with all of the code from the above tutorial.
Check out Part 2 of the tutorial, we’ll get our first look at the new and exciting Cocos2D 2.0 branch, and write a custom shader to mask sprites!
In the meantime, if you have any questions or comments, please join the forum discussion below!