In the previous section, you might have noticed that we displayed an image using the SPImage object, but used an SPTexture object to set the button's image. So what is the difference between an image and a texture?
A texture is just the data that describes an image — like the file that is saved on your digital camera. You can't show anybody that file alone. It's all zeros and ones, after all. You need some device that can display the image, like your iPad.
In Sparrow, that device is called “SPImage”.
In order to make full use of GPU acceleration, Sparrow 'paints' the texture onto a quad (a geometric figure that looks like a flat rectangle). In other words, an Image is nothing else than a quad with a texture mapped onto it.
To create a texture, you initialize an object of type “SPTexture”.
// create the texture object SPTexture *texture = [SPTexture textureWithContentsOfFile:@"mushroom.png"]; // display the texture through an image SPImage *image = [SPImage imageWithTexture:texture]; // or do the same in one line: SPImage *image = [SPImage imageWithContentsOfFile:@"mushroom.png"];
Every texture you create takes up precious memory. So, if you need to display something multiple times simultaneously, load the texture only once, and use different SPImage objects to display them.
In the samples above, we've always used PNG files for our textures. Sparrow supports more file formats, though, and each has specific advantages and disadvantages.
For now, you know enough about textures to use them in Sparrow. We will revisit the topic a little later, though. If you want to peek ahead, you'll find more information here: Texture Formats.
Even if all the previous samples created textures directly from PNG files, a real application should not do that. Here's why.
By using a texture atlas, you avoid both the texture switches and the power-of-two limitation. All textures are within one big “super-texture”, and Sparrow takes care that the correct part of this texture is displayed. (Some other frameworks call this feature “Sprite Sheets”.)
The trick is to have OpenGL use this big texture instead of the small ones, and to map only a part of it to the quad you are drawing. If the images are arranged in a smart way (more on that later), this will lead to a very efficient memory usage, wasting as little space as possible.
The positions of each sub-texture are defined in an XML file like this one:
<TextureAtlas imagePath="atlas.png"> <SubTexture name="moon" x="0" y="0" width="30" height="30"/>; <SubTexture name="jupiter" x="30" y="0" width="65" height="78"/>; ... </TextureAtlas>;
You don't have to create a texture atlas manually. You can use the following tools to create a texture atlas:
READMEfile in the same folder shows you how to install and use it.
So, now you have a texture atlas. But how do you use it?
Create a new “SPTextureAtlas” instance and access all subtextures through the “textureByName:” method. Create the atlas object once when the game is initialized and reference it throughout the lifetime of your game.
// load the atlas SPTextureAtlas *atlas = [SPTextureAtlas atlasWithContentsOfFile:@"atlas.xml"]; // display a sub-texture SPTexture *jupiterTexture = [atlas textureByName:@"jupiter"]; SPImage *jupiterImage = [SPImage imageWithTexture:jupiterTexture];
It's as simple as that!
Next Section: Displaying Text