Book Image

Cocos2d for iPhone 1 Game Development Cookbook

By : Nathan Burba
Book Image

Cocos2d for iPhone 1 Game Development Cookbook

By: Nathan Burba

Overview of this book

Cocos2d for iPhone is a robust but simple-to-use 2D game framework for iPhone. It is easy to use, fast, flexible, free, and Appstore approved. More than 2500 AppStore games already use it, including many best-seller games. Do you want to take your cocos2d game development skills to the next level and become more professional in cocos2d game design? Cocos2d for iPhone 1 Game Development Cookbook will help you reach that next level. You will find over 100 recipes here that explain everything from the drawing of a single sprite to AI pathfinding and advanced networking. Full working examples are emphasized. Starting with the first chapter, Graphics, you will be taken through every major topic of game development. You will find both simple and complex recipes in the book. Each recipe is either a solution to a common problem (playing video files, accelerometer steering) or a cool advanced technique (3D rendering, textured polygons). This cookbook will have you creating professional quality iOS games quickly with its breadth of working example code.
Table of Contents (15 chapters)
Cocos2d for iPhone 1 Game Development Cookbook
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Drawing sprites


The most fundamental task in 2D game development is drawing a sprite. Cocos2d provides the user with a lot of flexibility in this area. In this recipe we will cover drawing sprites using CCSprite, spritesheets, CCSpriteFrameCache, and CCSpriteBatchNode. We will also go over mipmapping . To keep things fun and interesting, many recipes in this book will have a distinct theme. In this recipe we see a scene with Alice from Through The Looking Glass.

Tip

You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.

Getting ready

Please refer to the project RecipeCollection01 for the full working code of this recipe.

How to do it...

Execute the following code:

@implementation Ch1_DrawingSprites
-(CCLayer*) runRecipe {
  /*** Draw a sprite using CCSprite ***/
  CCSprite *tree1 = [CCSprite spriteWithFile:@"tree.png"];
  
  //Position the sprite using the tree base as a guide (y anchor point = 0)
[tree1 setPosition:ccp(20,20)];
  tree1.anchorPoint = ccp(0.5f,0);
  [tree1 setScale:1.5f];
  [self addChild:tree1 z:2 tag:TAG_TREE_SPRITE_1];
  
  /*** Load a set of spriteframes from a PLIST file and draw one by name ***/
  
  //Get the sprite frame cache singleton
  CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];

  //Load our scene sprites from a spritesheet
  [cache addSpriteFramesWithFile:@"alice_scene_sheet.plist"];

  //Specify the sprite frame and load it into a CCSprite
  CCSprite *alice = [CCSprite spriteWithSpriteFrameName:@"alice.png"];
  
  //Generate Mip Maps for the sprite
  [alice.texture generateMipmap];
  ccTexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };  
  [alice.texture setTexParameters:&texParams];  
  
  //Set other information. 
  [alice setPosition:ccp(120,20)];
  [alice setScale:0.4f];
  alice.anchorPoint = ccp(0.5f,0);

  //Add Alice with a zOrder of 2 so she appears in front of other sprites
  [self addChild:alice z:2 tag:TAG_ALICE_SPRITE];
  
  //Make Alice grow and shrink.
  [alice runAction: [CCRepeatForever actionWithAction:
    [CCSequence actions:[CCScaleTo actionWithDuration:4.0f scale:0.7f], [CCScaleTo actionWithDuration:4.0f scale:0.1f], nil] ] ];  
  
  /*** Draw a sprite CGImageRef ***/
  UIImage *uiImage = [UIImage imageNamed: @"cheshire_cat.png"];
  CGImageRef imageRef = [uiImage CGImage];
  CCSprite *cat = [CCSprite spriteWithCGImage:imageRef key:@"cheshire_cat.png"];
  [cat setPosition:ccp(250,180)];
  [cat setScale:0.4f];
  [self addChild:cat z:3 tag:TAG_CAT_SPRITE];

  /*** Draw a sprite using CCTexture2D ***/
  CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:@"tree.png"];
  CCSprite *tree2 = [CCSprite spriteWithTexture:texture];
  [tree2 setPosition:ccp(300,20)];
  tree2.anchorPoint = ccp(0.5f,0);
  [tree2 setScale:2.0f];
  [self addChild:tree2 z:2 tag:TAG_TREE_SPRITE_2];

  /*** Draw a sprite using CCSpriteFrameCache and CCTexture2D ***/
  CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:tree2.textureRect];
  [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFrame:frame name:@"tree.png"];
  CCSprite *tree3 = [CCSprite spriteWithSpriteFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"tree.png"]];
  [tree3 setPosition:ccp(400,20)];
  tree3.anchorPoint = ccp(0.5f,0);
  [tree3 setScale:1.25f];
  [self addChild:tree3 z:2 tag:TAG_TREE_SPRITE_3];

  /*** Draw sprites using CCBatchSpriteNode ***/
  
  //Clouds
  CCSpriteBatchNode *cloudBatch = [CCSpriteBatchNode batchNodeWithFile:@"cloud_01.png" capacity:10];
  [self addChild:cloudBatch z:1 tag:TAG_CLOUD_BATCH];
  for(int x=0; x<10; x++){
    CCSprite *s = [CCSprite spriteWithBatchNode:cloudBatch rect:CGRectMake(0,0,64,64)];
    [s setOpacity:100];
    [cloudBatch addChild:s];
    [s setPosition:ccp(arc4random()%500-50, arc4random()%150+200)];
  }
  
  //Middleground Grass
  int capacity = 10;
  CCSpriteBatchNode *grassBatch1 = [CCSpriteBatchNode batchNodeWithFile:@"grass_01.png" capacity:capacity];
  [self addChild:grassBatch1 z:1 tag:TAG_GRASS_BATCH_1];
  for(int x=0; x<capacity; x++){
    CCSprite *s = [CCSprite spriteWithBatchNode:grassBatch1 rect:CGRectMake(0,0,64,64)];
    [s setOpacity:255];
    [grassBatch1 addChild:s];
    [s setPosition:ccp(arc4random()%500-50, arc4random()%20+70)];
  }
  
  //Foreground Grass
  CCSpriteBatchNode *grassBatch2 = [CCSpriteBatchNode batchNodeWithFile:@"grass_01.png" capacity:10];
  [self addChild:grassBatch2 z:3 tag:TAG_GRASS_BATCH_2];
  for(int x=0; x<30; x++){
    CCSprite *s = [CCSprite spriteWithBatchNode:grassBatch2 rect:CGRectMake(0,0,64,64)];
    [s setOpacity:255];
    [grassBatch2 addChild:s];
    [s setPosition:ccp(arc4random()%500-50, arc4random()%40-10)];
  }

  /*** Draw colored rectangles using a 1px x 1px white texture ***/

  //Draw the sky using blank.png
  [self drawColoredSpriteAt:ccp(240,190) withRect:CGRectMake(0,0,480,260) withColor:ccc3(150,200,200) withZ:0];
  
  //Draw the ground using blank.png
  [self drawColoredSpriteAt:ccp(240,30) withRect:CGRectMake(0,0,480,60) withColor:ccc3(80,50,25) withZ:0];

  return self;
}

-(void) drawColoredSpriteAt:(CGPoint)position withRect:(CGRect)rect withColor:(ccColor3B)color withZ:(float)z {
  CCSprite *sprite = [CCSprite spriteWithFile:@"blank.png"];
  [sprite setPosition:position];
  [sprite setTextureRect:rect];
  [sprite setColor:color];
  [self addChild:sprite];
  
  //Set Z Order
  [self reorderChild:sprite z:z];
}

@end

How it works...

This recipe takes us through most of the common ways of drawing sprites:

  • Creating a CCSprite from a file:

    First, we have the simplest way to draw a sprite. This involves using the CCSprite class method as follows:

    +(id)spriteWithFile:(NSString*)filename;

    This is the most straightforward way to initialize a sprite and is adequate for many situations.

  • Other ways to load a sprite from a file:

    After this, we will see examples of CCSprite creation using UIImage/CGImageRef, CCTexture2D, and a CCSpriteFrame instantiated using a CCTexture2D object. CGImageRef support allows you to tie Cocos2d into other frameworks and toolsets. CCTexture2D is the underlying mechanism for texture creation.

  • Loading spritesheets using CCSpriteFrameCache:

    Next, we will see the most powerful way to use sprites, the CCSpriteFrameCache class. Introduced in Cocos2d-iPhone v0.99, the CCSpriteFrameCache singleton is a cache of all sprite frames. Using a spritesheet and its associated PLIST file (created using Zwoptex, more on this later) we can load multiple sprites into the cache. From here we can create CCSprite objects with sprites from the cache:

    +(id)spriteWithSpriteFrameName:(NSString*)filename;
  • Mipmapping:

    Mipmapping allows you to scale a texture or to zoom in or out of a scene without aliasing your sprites. When we scale Alice down to a small size, aliasing will inevitably occur. With mipmapping turned on, Cocos2d dynamically generates lower resolution textures to smooth out any pixelation at smaller scales. Go ahead and comment out the following lines:

    [alice.texture generateMipmap];
      ccTexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };  
      [alice.texture setTexParameters:&texParams];

    Now you should see this pixelation as Alice gets smaller.

  • Drawing many derivative sprites with CCSpriteBatchNode:

    The CCSpriteBatchNode class, added in v0.99.5, introduces an efficient way to draw and re-draw the same sprite over and over again. A batch node is created with the following method:

    CCSpriteBatchNode *cloudBatch = [CCSpriteBatchNode batchNodeWithFile:@"cloud_01.png" capacity:10];

    Then, you create as many sprites as you want using the follow code:

    CCSprite *s = [CCSprite spriteWithBatchNode:cloudBatch rect:CGRectMake(0,0,64,64)];
      [cloudBatch addChild:s];

    Setting the capacity to the number of sprites you plan to draw tells Cocos2d to allocate that much space. This is yet another tweak for extra efficiency, though it is not absolutely necessary that you do this. In these three examples we draw 10 randomly placed clouds and 60 randomly placed bits of grass.

  • Drawing colored rectangles:

    Finally, we have a fairly simple technique that has a variety of uses. By drawing a sprite with a blank 1px by 1px white texture and then coloring it and setting its textureRect property we can create very useful colored bars:

    CCSprite *sprite = [CCSprite spriteWithFile:@"blank.png"];
    [sprite setTextureRect:CGRectMake(0,0,480,320)];
    [sprite setColor:ccc3(255,128,0)];

    In this example we have used this technique to create very simple ground and sky backgrounds.