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

Swapping palettes using CCTexture2DMutable


Another way to palette swap involves sentinel colors and the ability to modify a texture pixel by pixel. This method can help reclaim some extra space on the disk and in memory but it tends to take a lot of CPU time. It is also messier than the previous technique when used with anti-aliased or blended textures.

Getting ready

Please refer to the project RecipeCollection01 for full working code of this recipe. Also note the included library CCTexture2DMutable that is not included in the book itself.

For this recipe you will need an image manipulation program. Once again I recommend the free and easy to use GIMP.

How to do it...

The first thing we will do is draw a sprite that contains colorable areas defined by sentinel colors. A sentinel color is usually a primary color that is easily recognizable and can be replaced programmatically. In this case we will use red, blue, and green:

It is best to avoid aliasing and blending as much as possible when using this technique. Adjusting your coloring algorithm's tolerance according to your texture can be tricky.

Now, execute the following code:

#import "CCTexture2DMutable.h"

@implementation Ch1_MutablePaletteSwapping

-(CCLayer*) runRecipe {
  //Create a nice looking background
  CCSprite *bg = [CCSprite spriteWithFile:@"baseball_bg_01.png"];
  [bg setPosition:ccp(240,160)];
  bg.opacity = 100;
  [self addChild:bg z:0 tag:0];

  /*** Animate 4 different fielders with different color combinations ***/

  //Set color arrays
  ccColor4B colors1[] = { ccc4(255,217,161,255), ccc4(225,225,225,255), ccc4(0,0,150,255) };
  ccColor4B colors2[] = { ccc4(140,100,46,255), ccc4(150,150,150,255), ccc4(255,0,0,255) };
  ccColor4B colors3[] = { ccc4(255,217,161,255), ccc4(115,170,115,255), ccc4(115,170,115,255) };
  ccColor4B colors4[] = { ccc4(140,100,46,255),  ccc4(50,50,50,255), ccc4(255,255,0,255) };

  //Create texture copy to use as an immutable guide.
  CCTexture2DMutable* textureCopy = [[[CCTexture2DMutable alloc] initWithImage:[UIImage imageNamed:@"fielder_run_sentinel_colors.png"]] autorelease];

  //Create our sprites using mutable textures.
  CCSprite *sprite1 = [CCSprite spriteWithTexture:[[[CCTexture2DMutable alloc] initWithImage:[UIImage imageNamed:@"fielder_run_sentinel_colors.png"]] autorelease]];
  CCSprite *sprite2 = [CCSprite spriteWithTexture:[[[CCTexture2DMutable alloc] initWithImage:[UIImage imageNamed:@"fielder_run_sentinel_colors.png"]] autorelease]];
  CCSprite *sprite3 = [CCSprite spriteWithTexture:[[[CCTexture2DMutable alloc] initWithImage:[UIImage imageNamed:@"fielder_run_sentinel_colors.png"]] autorelease]];
  CCSprite *sprite4 = [CCSprite spriteWithTexture:[[[CCTexture2DMutable alloc] initWithImage:[UIImage imageNamed:@"fielder_run_sentinel_colors.png"]] autorelease]];

  //Set sprite positions
  [sprite1 setPosition:ccp(125,75)];
  [sprite2 setPosition:ccp(125,225)];
  [sprite3 setPosition:ccp(325,75)];
  [sprite4 setPosition:ccp(325,225)];

  //Swap colors in each sprite mutable texture and apply the changes.
  [self swapColor:ccc4(0,0,255,255) withColor:colors1[0] inTexture:sprite1.texture withCopy:textureCopy];
  [self swapColor:ccc4(0,255,0,255) withColor:colors1[1] inTexture:sprite1.texture withCopy:textureCopy];
  [self swapColor:ccc4(255,0,0,255) withColor:colors1[2] inTexture:sprite1.texture withCopy:textureCopy];
  [sprite1.texture apply];

  /* CODE OMITTED */

  //Finally, add the sprites to the scene.
  [self addChild:sprite1 z:0 tag:0];
  [self addChild:sprite2 z:0 tag:1];
  [self addChild:sprite3 z:0 tag:2];
  [self addChild:sprite4 z:0 tag:3];
  
  return self;
}

-(void) swapColor:(ccColor4B)color1 withColor:(ccColor4B)color2 inTexture:(CCTexture2DMutable*)texture withCopy:(CCTexture2DMutable*)copy {
  //Look through the texture, find all pixels of the specified color and change them.
  //We use a tolerance of 200 here.
  for(int x=0; x<texture.pixelsWide; x++){
    for(int y=0; y<texture.pixelsHigh; y++){
      if( [self isColor:[copy pixelAt:ccp(x,y)] equalTo:color1 withTolerance:200] ){
        [texture setPixelAt:ccp(x,y) rgba:color2];
      }
    }
  }    
}

-(bool) isColor:(ccColor4B)color1 equalTo:(ccColor4B)color2 withTolerance:(int)tolerance {
  //If the colors are equal within a tolerance we change them.
  bool equal = YES;
  if( abs(color1.r - color2.r) + abs(color1.g - color2.g) + 
    abs(color1.b - color2.b) + abs(color1.a - color2.a) > tolerance ){
      equal = NO;
  }
  return equal;
}

@end

How it works...

For better or worse this technique works the same way color selection and replacement works in Adobe Photoshop, and similar drawing programs. Using CCTexture2DMutable can often be a slow process and this technique is only recommended for games that require pixel-perfect graphics or have very strict space/memory requirements.