Texture mapping is a standard technique used to display images in iOS games and apps. In iOS devices, textures are constrained to dimensions with a power of two. In other words, the width or the height of a texture can only be in terms of 2, 4, 8, 16, 32, 64, 128, 256, 512 or 1024 (pixels). From iOS 4 onwards, textures can be as wide or as high as 2048 pixels.
A texture comes into play when we create a sprite from an image file. For example, we use the cocos2d CCSprite class to instantiate a sprite in a game using an image file:-
CCSprite *target = [CCSprite spriteWithFile:@"Target.png"
rect:CGRectMake(0, 0, 27, 40)];
If Target.png in the above example is 260 x 260 pixels in dimension with 32-bit colors, it should in theory use only 270 KB. But if we attempt this in iOS, we will discover that it actually uses 1 MB!
This unexpected increase is due to the constraint that texture need to be powers of 2 in its width and its height. iOS has created the next best texture of 512 x 512 (since 260 x 260 just missed 256 x 256 by 4 pixels in each attribute) and this uses 1 MB of memory.
The simple solution is to create image files that takes the powers-of-two rule into account. Taking care of this little detail goes a long way towards solving memory and performance related issues when rendering images in your iOS game or app.
As we are familiar by now, cocos2d organizes everything in nodes. Each node has an anchor point and by default, the anchorPoint property is 0.5, 0.5 which is half the size of the texture and 0.5, 0.5 is measured in terms of % (i.e. a factor of the texture size).
anchorPoint and node position are completely different concepts. When we change the anchorPoint and we see a sprite change its position on screen, the node’s position does not actually change. We are merely moving the sprite’s texture around.
In short, the anchorPoint is an offset of the texture relative to the node’s position. Setting our anchorPoint to 0,0 effectively places the texture’s lower left corner at the node’s position. Therefore, in this example, the sprite image will neatly align with the lower left corner of the screen:
CCSprite* sprite = [CCSprite spriteWithFile:@"Default.png"];
sprite.anchorPoint = CGPointMake(0,0);
[self addChild:sprite];
This is a simple example but for all practical purposes, we usually want our anchorPoint at the center of the texture and we usually do not want to specify the anchorPoint to 0,0.
In cocos2d game development, CCSprite is one of our best pals. It is a class which uses an image to display the sprite onscreen. To create a sprite, we first load an image file into a CCTexture2D texture and then assign this texture to the sprite. We will also need to make sure that this image file has been added into the Resources group in Xcode so that our app will be able to find the file. So here’s an example of how our sprite is instantiated:
CCSprite* sprite = [CCSprite spriteWithFile:@"Default.png"]
[self addChild:sprite];
When our sprite in instantiated, the texture is centered in the sprite’s position and the sprite which has just been initialized will be located at position 0,0 – the lower left corner of the screen. Because the sprite’s texture is centered on the sprite’s position, the texture will be only partially visible. Assuming that the image is 60 x 30-pixels in size, we will have to move our sprite to position 30, 15 to make the texture align perfectly with the lower left corner of the screen and be fully visible.
The other important point to note is that file names are case sensitive in iOS. So if our file name is “Default.png”, it has to be spelled exactly that to avoid your app crashing inexplicably.