Cocos2d Tip #1: Changing a Sprite’s Image Simply

I’m writing an iPhone game using the Cocos2d-iPhone framework. It’s been smooth sailing except for one little detail: I want a sprite to change it’s image based on a touch.

I think the problem is that there are a dozen ways to do this in Cocos2d. I wanted to find the simplest way to do it.  A quick Google search pointed me in the direction of CCAnimationCache and CCTextureCache.

CCAnimationCache is used for running multi-frame animations inside a single sprite. I only have 2 frames for my sprite! CCAnimationCache could do it but it’s a more power than I need to respond to a touch. (If you want to give animation a try check out Ray Wenderlich’s wonderful tutorial.)

CCTextureCache would have been the way to go if I hadn’t already used CCSpriteFrameCache to load all my sprite images at the start of my game. CCSpriteFrameCache uses a plist that divides up a large image into rectangle so you can pack all your sprite images into one memory saving “texture atlas.” And you can use Zwoptex to generate the image and the plist for you. CCTextureCache is the manual way to do what CCSpriteFrameCache and Zwoptex automates for you. (If you like to be hard core check out Ben’s post on optimizing texture loading.)

I figured there had to be a way to use my sprite frames in my existing cache without having to resort to manually loading textures or creating animations I didn’t need.

There was! It’s simple and here’s how to do it…

First, create your texture atlas with Zwoptex and add the .plist and .png files to your Resources folder in your Xcode project.

Second, load the texture atlas into the shared frame cache early in your game…

CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"textureAtlas.png"];

Third, create your sprite in your layer’s – init method…

// Note: niceSprite is a CSprint* instance variable so we can reuse it
niceSprite = [CCSprite spriteWithSpriteFrameName:@"initial_image.png"];
niceSprite.position = CGPointMake(240, 160);
[self addChild:niceSprite z:0 tag:0];

Fourth, in your – ccTouchBegan or – ccTouchesBegan method add the following code to change the image associated with your sprite…

CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCSpriteFrame* frame = [frameCache spriteFrameByName:@"new_image.png"];
[niceSprite setDisplayFrame:frame];

That was easy!






8 responses to “Cocos2d Tip #1: Changing a Sprite’s Image Simply”

  1. pav Avatar

    Made githut gist out of the code snipets above:

    git clone git:// gist-818754

  2. Emmy Chen Avatar

    This is exactly what I am looking for. Thank you so much.

  3. Chris Hunn Avatar
    Chris Hunn

    This was my first google hit for exactly the same problem, thanks for sharing this.

  4. Garrett Hedman Avatar
    Garrett Hedman

    3 hours later I found your blog. OH MY GOSH thank you! The tricky part I had was reloading the cache in the touch methods to gain access to frames… ooo tricky tricky.

  5. Anvar Avatar

    YEAH!!! Very very nice! Thank you so much.

  6. Martin Avatar

    Thanks! I needed to set the image again in cocos2D-HTML5 inside the update cell mechanism in the tableview tableCellAtIndex:function (table, idx).
    I did this:
    icon = cell.getChildByTag(TAG);
    frame = spriteFrameCache.getSpriteFrame(image);

  7. Jyothsna Avatar

    How we can we create and load the texture atlas into the shared frame cache early in our game…
    the only point i am not getting i have already two created sprites…what is this ” texture atlas”

    Kindly explain me sir….I am new learner to the cocos2d currently i am using cocos2dx-2.0.4

  8. pav Avatar

    I’m a Cocos2d-iphone guy moving over to sprite kit. I’ve heard good things about cocos2dx but I’ve never used it. This might help: