I’ve gotten a ton of requests from readers of this blog to make a tutorial on how to use animations and sprite sheets in Cocos2D. You asked for it, you got it!
In this tutorial, we will show how to create a simple animation of a bear walking in Cocos2D. We’ll also cover how to make them efficient by using sprite sheets, how to make our bear move in response to touch events, and how to change the direction the bear faces based on where the bear is moving.
If you are new to Cocos2D, you may wish to go through the tutorial series on How To Make A Simple iPhone Game With Cocos2D first, but this is not required!
Getting Started
Let’s start by creating a skeleton for our project – create a new project with the Cocos2D project template and name it AnimBear.
Next, go ahead and download some images of an animated bear made by my lovely wife.
When you unzip the file, take a look at the images – they are just individual frames of a bear that when you put them together, look like the bear is moving.
We could just add these directly to our Cocos2D project at this point and create an animation based on these individual images. However, there’s another way to create animations in Cocos2D that is much more efficient – by using sprite sheets.
Sprite Sheets and Bears, Oh My!
If you haven’t used sprite sheets yet, think of them as gigantic images that you put your sprites within. They come with a file that specifies the boundaries for each individual sprite so you can pull them out when you need them within the code.
The reason why these are such a good idea to use is because Cocos2D is optimized for them. If you use sprites within a sprite sheet properly, rather than making one OpenGL ES draw call per sprite it just makes one per sprite sheet.
In short – it’s faster, especially when you have a lot of sprites!
As for sprite sheets, you could actually create them yourself manually with your image editor and create the file that specifies the boundaries yourself by hand as well.
However, this would be crazy talk because Robert Payne has developed an amazing app called Zwoptex that does this automatically for us!
Zwoptex To Victory!
If you don’t have it already, go ahead and download a copy of Zwoptex from zwoptexapp.com. There’s an online Flash version and a downloadable version, but these days I use the downloadable version.
Once you have the app installed, go to File\New and you will see a blank window appear. Open up the folder where you downloaded all of the bear images, and drag them into the view.
You’ll notice that all the bear images are on top of each other. We need them to be spread out in our sprite sheet, so click “Apply” in the Layout section to sort them.
When you do that, you’ll notice that there’s not enough space in the default canvas (512×512) to fit all of the sprites, so some still overlap. So increase the space to 512×1024 in the Canvas section and click “Apply” in the Layout section to re-sort them.
We’re getting close – but notice how some of the bear images are wider than others. If you look at the original images, that isn’t the way they were made – but by default Zwoptex trims the images to remove any transparency around them.
For these images, this isn’t what we want because it would mess up the positioning of the bear for the animations. Luckily, this is easy to fix – just click Untrim in the toolbar up top, and click “Apply” in the Layout section to re-sort one final time.
At this point, your window should look similar to the following:
And that’s it! So let’s save the spritesheet image and definitions so we can use them in our app.
Click “Save .jpg” in the Export section, and save the Png to the resources folder of your project as “AnimBear.jpg”. Then click “Save .plist” in the Export section, and save the plist to the resources folder of your project as “AnimBear.plist”.
Update: When saving your files in Zwoptex, be sure to pick “Cocos2D” as the format, or else your plist will not load properly in Cocos2D! Thanks to Muhammad in the comments section for pointing this out.
Now let’s go back to XCode and add these to your project. Right click on the Resources folder of your project, click “Add\Existing Files…”, select AnimBear.jpg and AnimBear.plist from your Resources folder, and click Add.
While you’re at it, click on AnimBear.plist in XCode to see what Zwoptex did for us. You’ll see that it’s just a property list with two sections – frames and metadata. In the frames section, there is an entry for each of the images in the spritesheet, with properties inside that give the bounding box for the image within the spritesheet. Cool eh?
But what would be even cooler is an animated bear! So let’s get to it!
A Simple Animation
We’re going to start just by plopping our bear in the middle of the screen and looping the animation so he moves forever, just to make sure things are working.
So let’s start by adding a few properties we’ll need in this tutorial into HelloWorldScene.h. Make the following modifications to the file:
// Add inside the HelloWorld interface CCSprite *_bear; CCAction *_walkAction; CCAction *_moveAction; BOOL _moving; // Add after the HelloWorld interface @property (nonatomic, retain) CCSprite *bear; @property (nonatomic, retain) CCAction *walkAction; @property (nonatomic, retain) CCAction *moveAction; |
We actually don’t need all of these properties right away, but we’re putting them in place now so we don’t have to go back and change the code later.
Now, to the fun stuff! Move over to HelloWorldScene.m and make the following changes to the file:
// At the top, under @implementation @synthesize bear = _bear; @synthesize moveAction = _moveAction; @synthesize walkAction = _walkAction; // In dealloc self.bear = nil; self.walkAction = nil; // Replace the init method with the following -(id) init { if((self = [super init])) { // Add the stuff from below! } return self; } |
There are 5 steps we need to take to get this animation to work, so let’s cover them one at a time. Add each of these snippets to your init method in the area shown by the comment.
1) Cache the sprite frames and texture
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: @"AnimBear.plist"]; |
First, we make a call to the shared CCSpriteFrameCache’s addSpriteFramesWithFile method, and pass in the name of the property list that Zwoptex generated for us. This method does the following:
- Looks for an image with the same name as the passed-in property list, but ending with “.jpg” instead, and loads that file into the shared CCTextureCache (in our case, AnimBear.jpg).
- Parses the property list file and keeps track of where all of the sprites are, using CCSpriteFrame objects internally to keep track of this information.
2) Create a sprite batch node
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"AnimBear.jpg"]; [self addChild:spriteSheet]; |
Next, we create a CCSpriteBatchNode object, passing in the image of our sprite sheet. The way sprite sheets work in Cocos2D is the following:
- You create a CCSpriteBatchNode object passing in the image file containing all of the sprites, as we did here, and add that to your scene.
- Now, any time you create a sprite that comes from that sprite sheet, you should add the sprite as a child of the CCSpriteBatchNode. As long as the sprite comes from the sprite sheet it will work, otherwise you’ll get an error.
- The CCSpriteBatchNode code has the smarts to look through its CCSprite children and draw them in a single OpenGL ES call rather than multiple calls, which again is much faster.
Note: CCSpriteBatchNode used to be called CCSpriteSheet, so you may see it called that in some older code.
3) Gather the list of frames
NSMutableArray *walkAnimFrames = [NSMutableArray array]; for(int i = 1; i <= 8; ++i) { [walkAnimFrames addObject: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:@"bear%d.jpg", i]]]; } |
To create the list of frames, we simply loop through our images names (they are named with a convention of Bear1.jpg -> Bear8.jpg) and try to find a sprite frame by that name in the shared CCSpriteFrameCache. Remember, these should already be in the cache because we called addSpriteFramesWithFile earlier.
4) Create the animation object
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f]; |
Next, we create a CCAnimation by passing in the list of sprite frames, and specifying how fast the animation should play. We use a 0.1 second delay between frames here.
5) Create the sprite and run the animation action
CGSize winSize = [CCDirector sharedDirector].winSize; self.bear = [CCSprite spriteWithSpriteFrameName:@"bear1.jpg"]; _bear.position = ccp(winSize.width/2, winSize.height/2); self.walkAction = [CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]]; [_bear runAction:_walkAction]; [spriteSheet addChild:_bear]; |
We then create a sprite for our bear passing in a frame to start with, and center it in the middle of the screen. We then set up an CCAnimateAction telling it the name of the CCAnimation to use, and tell the bear to run it!
Finally, we add the bear to the scene – by adding it as a child of the sprite sheet! Note that if we did not add it as a child of the spritesheet and instead added it as a child of the layer, we would not get the performance benefits (such as if we had several bears).
Done!
And that’s it! So compile and run the project, and if all goes well you should see your bear happily strolling on the screen!
Changing Animation Facing Direction Based on Movement
Things are looking good – except we don’t want this bear meandering about on its own, that would be dangerous! Would be much better if we could control its movement by touching the screen to tell it where to go.
So make the following changes to HelloWorldScene.m:
// Comment out the runAction method in the init method: //[_bear runAction:_walkAction]; // And add this to the init method self.isTouchEnabled = YES; // Add these new methods -(void) registerWithTouchDispatcher { [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES]; } -(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { return YES; } -(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { // Stuff from below! } -(void)bearMoveEnded { [_bear stopAction:_walkAction]; _moving = FALSE; } |
Starting at the beginning, we comment out running the walk action in the init method, because we don’t want our bear moving until we tell him to!
We also set the layer as touch enabled, and implement registerWithTouchDispatcher and ccTouchBegan. If you are curious as to the advantages of using this method rather than plain ccTouchesBegan, check out an explanation in the How To Make a Tile Based Game with Cocos2D Tutorial.
When the bearMoveEnded method is called, we want to stop any running animation and mark that we’re no longer moving.
As for the ccTouchEnded function, this is where the meat of our code is. There’s a lot of stuff here, so we’re going to break it into steps like we did before – X this time!
1) Determine the touch location
CGPoint touchLocation = [touch locationInView: [touch view]]; touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation]; touchLocation = [self convertToNodeSpace:touchLocation]; |
Nothing new here – we just start by converting the touch point into local node coordinates using our usual method.
2) Set the desired velocity
float bearVelocity = 480.0/3.0; |
Here we set up a velocity for the bear to move. I estimated that it should take about 3 seconds for the bear to move the width of the iPhone screen (480 pixels), so since velocity is distance over time it would be 480 pixels / 3 seconds.
3) Figure out the amount moved in X and Y
CGPoint moveDifference = ccpSub(touchLocation, _bear.position); |
Next we need to figure out how far the bear is moving along both the x and y axis. We can do this by simply subtracting the bear’s position from the touch location. We use a helper function Cocos2D provides called ccpSub to do this.
4) Figure out the actual length moved
float distanceToMove = ccpLength(moveDifference); |
We then need to calculate the distance that the bear actually moves along a straight line (the hypotenuse of the triangle). Cocos2D has a helper function to figure this out based on the offset moved: ccpLength, which we use here!
5) Figure out how long it will take to move
float moveDuration = distanceToMove / bearVelocity; |
Finally, we need to calculate how long it should take the bear to move this length, so we simply divide the length moved by the velocity to get that.
6) Flip the animation if necessary
if (moveDifference.x < 0) { _bear.flipX = NO; } else { _bear.flipX = YES; } |
Next, we look to see if the bear is moving to the right or to the left by looking at the move difference. If it’s less than 0, we’re moving to the left and we can play our animation as-is. However, if it’s moving to the right we need to flip our animation to the other way!
Our first instinct might be to run to our image editor and create new images for the bear facing the other direction, and use those. However Cocos2D has a much easier (and more efficient) way – we can simply flip the existing images!
The way it works, you actually set a flip value on the sprite the animation is run on, and it will cause any animation frames that is run on the sprite to be flipped as well. So in the case we are moving the bear to the right, we set flipX to YES.
7) Run the appropriate actions
[_bear stopAction:_moveAction]; if (!_moving) { [_bear runAction:_walkAction]; } self.moveAction = [CCSequence actions: [CCMoveTo actionWithDuration:moveDuration position:touchLocation], [CCCallFunc actionWithTarget:self selector:@selector(bearMoveEnded)], nil]; [_bear runAction:_moveAction]; _moving = TRUE; |
Next, we stop any existing move action (because we’re about to override any existing command to tell the bear to go somewhere else!) Also, if we’re not moving, we stop any running animation action. If we are already moving, we want to let the animation continue so as to not interrupt its flow.
Finally, we create the move action itself, specifying where to move, how long it should take, and having a callback to run when it’s done. We also record that we’re moving at this point.
Done!
A lot of code – but was it worth it? Compile and run to see! If all works well you should be able to tap the screen to move your bear all around.
Where To Go From Here?
Here is a sample project with all of the code we’ve developed in the above tutorial.
At this point, you should know how to use animations in your projects. You should have some fun and experiment by creating your own animations and seeing what you can do!
Category: iPhone












excellent work on the tutorial – very clear.
Do you really need to untrim for positioning? Doesn’t the .plist keep the original rect and you then save space in the spritesheet?
Hi Ray,
This is great. Any chance you can add the following (cheeky I know):
1) How to advance to a specific animiation frame…
2) How to return the bear to a stationary position once stopped walking…
3) Simple bounding box collision detection, as I believe when you do collision detection with sprites on spritesheets…your bounding rectangle can sometimes not be the sprite frame but the whole spritesheet (from reading some of the Cocos forums).
Thanks as always…you are a Cocos legend!
Regards
i
p.s. CCTouchDispatcher tutorial would be great ;–)
@Dale – the issue is your sprite would wobble all over the place…you need the bear to remain in the same position throughout its animation….not to move left just because the bears front leg moved back and the sprite got trimmed…
@indy
…the issue is your sprite would wobble all over the place…you need the bear to remain in the same position throughout its animation….
I could have sworn that I was able to trim several elements in a spritesheet with a common size and keep them registered to the original without wobbling. I may need to review my experiments.
btw. Great tutorial, always enjoy your stuff.
@Dale…you may be right if the sprite is anchored at the centre as in this instance..I tend to set my anchor point at bottom left which would cause my wobble (and cause my flipX to fail miserably).
Not sure if there is an issue with CGRect type collision detection if the frames are different sizes
@Ray…looking at the code, you are setting the position of the bear within the CCSpriteSheet rather than the main layer, correct? That always confuses me, if so – do you need to set the position of the CCSpriteSheet instance at all on init, as well as adding it as a child to the main layer?
Awesome icon! Took me a couple of seconds to figure it out :) Great tut
Another fantastic tutorial! Question though: I read that spritesheets should always be 512×512, 1024×1024, etc. since a 512×1024 spritesheet would use the same memory as a 1024×1024 spritesheet. Is this true?
@Dale: When I was first writing the tutorial, at first I didn’t untrim the images so the bear appeared to “wobble” as Indy mentioned… so maybe there’s some option to get Zwoptex to be smart about the rect as you mentioned, but I am not aware of it so had to go with the untrim route :]
@Indy: Good ideas, added to my idea list! Regarding the sprite sheet question: yes the coordinate is with respect to the sprite sheet, but since the sprite sheet is at 0,0 it’s effectively the same as putting a sprite within the coordinates of the layer. You can prove it by moving the position of the sprite sheet to like (200,200) and you’ll see the bear will move too. Not sure why you’d ever want to do that though!
@SC: I thought as long as the sprite sheet was a power of 2 in both dimensions that is fine, so it doesn’t have to be a perfect square. Let me know if I’m wrong though!
Fantastic tutorial. As additional work I am trying to programmatically switch to frame x in a CCSpriteSheet animation based on a user action, then stay there until another action. Can this be done? Or do you have a suggestion on the best way to achieve this? CCSpriteSheet just seems really efficient given these frames will happen over and over.
No questions here, just want to let you know that you’re an inspiration. Tile based games, shooting games and now a walking bear!
I love that every project leaves me with a ‘I wonder if I can…’ kind of question that really encourages me to delve into the code and learn Objective C and cocos2d the fun way. Fantastic!
@Mike: If you just want to display a single frame, you can just set the texture of the sprite to the appropriate texture from the sprite sheet.
@Chris: Wow, thanks for the kind words! That made my day, I love to hear people getting into making games :]
Hi ray. first comment here but i’m a fan for quite some time now… appreciate everything you’re doing ,your really hitting the right spotes!
Q: how would you switch an animation with a different one?
say the bear will also be able to growl
1. create more frames in the same spriteSheet and create an animation from them?
2. create a different sprite and add and remove?
any thoughts?
Again… keep up this inspiring work.
Thanks yogi
How would you go about using a custom sprite class, that subclasses CCSprite, but also takes advantage of spritesheets? I pretty much have a custom sprite class that handles everything for a character (contains all the animation frames) and I’m looking to optimize it using spritesheets. I would love to load all the sprite sheets in the main game layer and then have my custom sprites use the sprite sheet as they spawn. Not really sure how the two mix.
I’ve actually updated the code but keep getting an error when adding the custom sprite to the game layer spritesheet. I keep getting “CCSprite is not using the same texture id”. Not sure how to resolve this really.
Thanks
Hi Ray, no doubt, this is really fantastic tutorial. Big Thanks for your kindness share this tutorial. I’ve run it at simulator and it runs well, but the problem occurs when I run the sample project on the device. I got message :
GDB : program received signal : EXC_BAD_ACCESS
and my iphone display stuck with cocos2d splash screen. I check in my xcode debugger, and I found nothing in there. Is this problem occurs because of memory management? or anything else?
I really hope you could help me to solve this problem.
Again, big thanks for your great tutorials.
Hi Ray,
in your tutorial, would the following two expressions load the “AnimBear.jpg” twice?
1. [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
@”AnimBear.plist”];
2. CCSpriteSheet *spriteSheet = [CCSpriteSheet spriteSheetWithFile:@"AnimBear.jpg"];
Or would the expression 2 only load the file from the cache created by expression 1?
Hi Ray,
If you wanted to animate without using actions, how do you manually set the texture frame a sprite should use? I have asked this question on Cocos2D forums, and was told to recreate the sprite each time with a different texture….
Regards
i
Wow lotta comments here! Here goes:
@yogi: Nice to meet you!
To switch the animation to a different one, simply repeat steps 1-5 in the “A Simple Animation” section above for a second action, but don’t run the action quite yet – just store it in an instance variable.
Then when you’re ready to run it, stop any other animations running (by running [_bear stopAction:_walkAction] for example), and start your growl action!
So to answer your question, option 1 woudl be better (create more frames in the sprite sheet and create an animation from them).
@TinyTechnician: Why hello there, see you all the time on Twitter! :]
You should be able to use custom subclasses of CCSprite with no problems as children of CCSpriteSheet. In fact that’s what I do in Math Ninja. CCSpriteSheet just has logic to see that all of its children are CCSprites (or subclasses), and draw them all in a single openGL call rather than multiple calls like usual.
If you’re getting an error like that, maybe you’re loading the texture two different times, or loading different images in your custom sprites vs. the spritesheets. Make sure when you’re setting up your custom sprites that they’re all using spriteWithSpriteFrameName, not spriteWithFile.
@aye: Not sure what the problem is without going through with the debugger. Here’s a few tips to help you figure it out:
1) Set a breakpoint in the init method for your layer and step through until you narrow down where the problem is occurring
2) Enable NSZombieEnabled in your project, which can sometimes give you additional information about memory issues: http://www.cocoadev.com/index.pl?NSZombieEnabled
@Leon: If you trace through the source for CCSpriteFrameCache::addSpriteFramesWithFile and CCSpriteSheet::spriteSheetWithFile, you’ll see both of them eventually make a call to sharedTextureCache::addImage. However this method checks to see if the image is already in the cache before loading it, so the AnimBear.jpg is only loaded once!
@indy: You can use the setDisplayFrame method on CCSprite to do this. In fact this is exactly what CCAnimate does (see line 1199).
Hi Ray,
Thank you for helpful tutorial!
But may I ask you a little question? Is there any way to detect number of animation frames in runtime? As I think it’s not good to hard code that…
I’m searching a little about that but didn’t find anything.
OK so now I init my custom sprite class with spriteFrame instead of spritefile…that seemed to fix the “not using the same texture id” error.
Now I’m getting an exception on SetDisplayFrame inside my custom sprite class. I have a feeling I probably just need to rewrite the custom sprite class altogether but might as well throw the code out there to see if it can be salvaged.
So on the gamelayer I create a custom sprite like so…(I’ve already setup the spritesheet and stuff like you have in the example btw)
CustomSprite *sprite;
sprite = [CustomSprite spriteWithSpriteFrameName:@"player_idle_01.jpg"]; // where “player_idle_01.jpg” is a frame in the spritesheet etc
[sprite AddAnimationWithFrame:@"player"]; // this is a custom function to load all the sprite animations in the sprite class
[self.spriteSheetPlayer addChild:sprite]; //add the custom sprite to the spritesheet
Then in my custom sprite class I have stuff like
-(void)AddAnimationWithFrame:(NSString *)frame
{
//create Animation objects to hold the frames for the cycles
idleAnimation = [[CCAnimation alloc] initWithName:@”idleAnimation” delay:0];
//Add each frame to the animation
[idleAnimation addFrame:[NSString stringWithFormat:@"%@%@", frame, @"_idle_01.jpg"]];
[idleAnimation addFrame:[NSString stringWithFormat:@"%@%@", frame, @"_idle_02.jpg"]];
and so forth…
//Add the animation to the sprite so it can access it’s frames
[self addAnimation:idleAnimation];
}
Eventually in the custom sprite class I play an animation using a tick method that calls…
[self setDisplayFrame:@"idleAnimation" index:currentFrame]; //currentFrame gets iterated
and here is where the exception is thrown…on the setDisplayFrame.
So I guess after all that my real question is how do I setup my animations in my custom sprite class so they will use the spritesheet in the gamelayer to render frames when I use the setDisplayFrame function?
I will still try and work this out on my own so don’t worry if you don’t have time to look at my specific issue. We’re all busy developers ;-)
Ha!!!
So about 5 mins after I comment about an issue I’m having…I end up fixing it on my own. In case anyone is interested, I simply had to change how I loaded the animation frames inside my custom sprite class…
So now I use this instead for my custom loading class…
-(void)AddAnimationWithFrame:(NSString *)frame
{
NSMutableArray *arrayidle = [[NSMutableArray alloc] init];
self.idleFrames = arrayidle;
[arrayidle release];
//Add each frame to the animation
[idleFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"%@%@", frame, @"_idle_01.jpg"]]];
[idleFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"%@%@", frame, @"_idle_02.jpg"]]];
and so forth…
//create Animation objects to hold the frames for the cycles
idleAnimation = [[CCAnimation alloc] initWithName:@”idleAnimation” delay:0 frames:idleFrames];
//Add the animations to the sprite so it can access it’s frames
[self addAnimation:idleAnimation];
}
Yay :-)
@cppboris: Hmm… well you could retrieve the frames in a sprite sheet and add them up to form an animation, but in practice I don’t know how useful that would be…
Probably in a real game you’re likely going to want to have some kind of file that you can set up with the names of the frames that consist of each animation. For example in some of my projects I’ve used XML to contain the game configuration, and I have set up walkAnim=”x.jpg,y.jpg”, and I parse that to pull out the frame names to create the animation.
Dunno if that is what you were looking for…?
@Tiny Technician: w00t glad you got it working!
Great!
thank u Ray
Really helpful man, explained so well. Keep posting!!!
NIce Work Ray .great tutorial very clear . is there a way to replace spritesheet with another spritesheet for example in this bear when walk this is great but when get idle suppose it doing some other work which totally a different sprite sheet how to handle that situation.. at the current position..
Thanks very much
hello ray how to flip the image with respect to specific angle i know it does work for flipX and flipY..
@umer: All children of a spritesheet must have textures that come from that spritesheet.
So I would recommend you try to make sure your animations for a particular sprite all come from the same sprite sheet. If this is not possible, you’ll have to do funky stuff like removing the sprite from the scene and re-adding it from another sprite sheet if you need to change the animation to one from a different sprite sheet.
Also, no way AFAIK to flip a texture to a specific angle other than flipX and flipY. However, you can always rotate the sprite itself using .rotate or CCRotateTo, etc.
thanks ray your help is always appreciated…
I really enjoy your tutorials! I have a problem with Animate Bear. I entered the code for animate bear in center of screen but I get a black screen. Im using 99.4-rc2 and xcode 3.2.3 simulator 4.0 target 3.0 and it compiles with no errors. Could it be the bears PNG format?
Kevin
I [spriteSheet addChild:_bear]; alone does not show bear walking but if I add [self addChild:spriteSheet]; now it shows the bear…
why?
@Kevin: That’s because you have to add the sprite sheet to the layer, so the layer can tell the sprite sheet “draw yourself and your children”. Then the sprite sheet can draw all of its children (such as the bear) in an optimized manner. Hope that makes sense!
Hi Ray
You did a great tutorial. I’m new on cocos2d and object-c and I have 2 big questions that might be of help not only to me but also to someone that wants to build a game like me.
On my game I have a spritesheet with 5 positions for the main character ( left,right,top,down,brief). What I want to do is to move the character on the left with one animation, move on the right with a different animation, and on top and down with other animation. The character walks only on the X coordinate, on the Y coordinate he just throw or pick up something. The best example for my character is on the Critter Crunch game for iphone.
Problem n. 1: to move on the left or on the right I use this code:
if (moveDifference.x < 0) {
// Player.flipX = NO;
[ self WalkLeft];
} else {
// Player.flipX = YES;
[ self WalkRight];
}
but each time I tap on the left or on the right a new character appears on the screen (but not all the time).
What I am trying to do is to move only one character either left or right. Just a simple walk left and right like the bear but with a specific animation.
Problem n. 2: the character should move only on the X coordinate and not on the Y coordinate. On the Y there are other animation.
In fact I have 2 1/2 questions… the last question is when the character doesn't move I would like to load an animation like a brief.
That all! I know this is a long post but those are my problem.
Regards
Rick
Thanks Ray,
Yeah, I forgot to add the [self addChild:spriteSheet]; to the code after creating the spriteSheet. :(
Now it works… :)
Ray, Thank you for tutorial.
By the way, when we will see 3D Tutorial (OpenGL) from Ray! :-)
Just waiting for it.
@Rick: If there’s another character appearing on the screen, I’d check your project for where you add sprites to the scene, and make sure you don’t have one in the wrong spot.
To make the character only move along the x axis, you control exactly where the sprite moves by setting its position or using actions like CCMoveTo/By – so just restrict the movement the way you would like!
To get the character to play an animation when it doesn’t move, one good way is to record the timestamp for when the character was last moved, and then in your game’s update loop get the difference between the current time and the last time moved, and play your idle animation if it’s been a certain length of time.
@Kevin: w00t!
@Jay: Hehe as soon as I learn it myself! I’m still a n00b in raw OpenGL – but it is pretty high on my priority list of things to learn next!
I have a 15 frame animation running at 15fps… and I use a naming convention of bear01.jpg, bear01.jpg etc… in my Zwoptex
However when I mod the code in your downloadable example I get a exception error.
I mod this…
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 8; ++i) {
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:@"bear%d.jpg", i]]];
}
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 8; ++i) {
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:@"bear%d.jpg", i]]];
}
to be (int i = 1; i <= 15; ++i) but I am not sure about bear%d.jpg …. that is where i suspect the problem is… Can you clarify if I am doing this right?
Sorry… should be
“I have a 15 frame animation running at 15fps… and I use a naming convention of bear01.jpg, bear02.jpg etc… in my Zwoptex”
Hey Ray,
Amazing tutorial especially on how to use Zwoptex. The trimming feature should automatically work with cocos2d and you shouldn’t experience any wobbling if you use cocos2d API. ( You’ll notice offsets, and sourceSize/sourceColorRect in the .plist ). cocos2d uses these variables to reposition the sprite each time the frame is updated to ensure playback is smooth while saving loads of texture memory.
If this isn’t the case please send me an email with the sample project, and the .zss file and I’ll investigate the rather large bug.
-Robert Payne
Hey Everyone,
After looking at the example and implementing it with “Trimming” enabled .jpg and .plist the wobbling is because cocos2d currently doesn’t support flipX/flipY with trimmed sprites.
If you use the latest development release of cocos2d (0.99.4.rc3 http://www.cocos2d-iphone.org/archives/1006) flipX/flipY support for trimmed sprites has been added.
-Robert Payne
will u please tell me how to move an animation on touch.Animation should move in the way touch is moved….
sud…
Great tutorials, Ray. They’ve helped my progress immensely.
@Dell: I think you want to say @”bear%02d.jpg” in your string format.
Thanks for the tutorial Ray.
I was able to incorporate the concepts into a little demo I was working on that did some touch delegation. And I’m noticing that the containsTouchLocation method that I wrote doesn’t work. Seems like it’s method of calculating the bounding box works fine for images sprites, but not so much for sprite sheet sprites. At this point do I need to just change my logic to be based on a position relative to the sprite position, and not calculated based on the size of the texture?
Hi, I am not sure where I am going wrong here. I can get it to run fine with my own sprite and plist generated from Zwoptex. However when I change the frame rate to 12 and use an AnimBear.jpg with 12 frames and a plist with 12 frames… it blows up… Here is my code below? Any ideas as to where I am going wrong?
-(id) init {
if((self = [super init])) {
CCSprite *bg = [CCSprite spriteWithFile:@"BG.jpg"];
[self addChild:bg z:0];
bg.position = ccp(510,380);
// This loads an image of the same name (but ending in jpg), and goes through the
// plist to add definitions of each frame to the cache.
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@”AnimBear.plist”];
// Create a sprite sheet with the Happy Bear images
CCSpriteSheet *spriteSheet = [CCSpriteSheet spriteSheetWithFile:@"AnimBear.jpg"];
[self addChild:spriteSheet];
// Load up the frames of our animation
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 12; ++i) {
[walkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"bear%02d.jpg", i]]];
}
CCAnimation *walkAnim = [CCAnimation animationWithName:@"walk" delay:0.1f frames:walkAnimFrames];
// Create a sprite for our bear
CGSize winSize = [CCDirector sharedDirector].winSize;
self.bear = [CCSprite spriteWithSpriteFrameName:@"bear01.jpg"];
_bear.position = ccp(winSize.width/2, winSize.height/2);
self.walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]];
//[_bear runAction:_walkAction];
[spriteSheet addChild:_bear];
self.isTouchEnabled = YES;
// Play a sound!
//[[CDAudioManager sharedManager] playBackgroundMusic:@"background-music-aac.caf" loop:YES];
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"background-music-aac.caf"];
emitter = [[CCQuadParticleSystem alloc] init];
emitter.position = ccp(240, 460);
emitter = [[CCQuadParticleSystem alloc] initWithFile:@"super.plist"];
[self addChild: emitter z:10];
}
return self;
}
Here is the error Message I am getting in the debugger if that helps…
*** Assertion failure in -[CCSpriteFrameCache addSpriteFramesWithDictionary:texture:], /Users/user_directory/Desktop/AnimBear/libs/cocos2d/CCSpriteFrameCache.m:111
2010-07-08 21:43:01.130 AnimBear-Upgraded[18054:207] *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:’
Hi Dell,
I’m going to assume you just recently upgraded to Zwoptex 1.0.0. Please see this blog post for integration details since the new version has a new .plist format for rotational support. I’m working with Riq to get it integrated into cocos2d as soon as possible.
http://zwopple.com/blog/2010/07/08/zwoptex-integrating-1-0-jpg-plist-with-cocos2d/
If you have trouble getting it to work open up a support request http://www.zwoptexapp.com/support.php and I’ll gladly assist you in getting this working.
Robert Payne
Zwopple, LLC
Ahhh yes… The answer has arrived! Thanks this is what did the trick. Now everything works great!
Thanks Ray and Robert!!
@Robert: Wow, thanks so much for helping out here! The flipX/Y thing makes perfect sense why I was seeing the wobbling earlier – and awesome that it has been fixed! Good to know about the 1.0.0 issue and fix as well.
And thanks for doing such a great job on Zwoptex – it’s an extremely useful app!
@Sudeep: It sounds like you may be looking to move a sprite along the path the user drags their finger, like in FlightControl? There’s been a lot of posts on the Cocos2D forums about this, check out this one as a good starting point:
http://www.cocos2d-iphone.org/forum/topic/1656
@John: Hm that’s weird, I have never had a problem using boundingBox for sprites from sprite sheets before. To get the size of a sprite, I usually use sprite.contentSize, and to get the bounds, [sprite boundingBox]. What are you using?
Hi,
I wonder if you know how to use z ordering between sprites of different sprite sheets. Ex: a bear sprite sheet and a fox sprite sheet. I’d like to have 4 sprites, two from each sheet, and the z order i’d like to have is: bear-fox-bear-fox. I’ve read that the vertexZ property might offer a solution, but my sprites are partially transparent and other problems arise.
Robi
@Peter: AFAIK there is no way to have different z-ordering between sprites of different sprite sheets – it’s a limitation of using sprite sheets. So if you want to be able to z-order objects, they’ll have to be on the same sprite sheet, or you can modify the z-order of the entire sprite sheet (and have one sprite sheet per object for example), or you can just not use sprite sheets. Yeah a pain, but there are lots of nice things about sprite sheets as well :]
Nice tutorial! Love the humor! :-)
Hi Ray,
just got an update notice from Zwoptex today that they are turning into a commercial software. What do you think about that – was it the right thing to do? From free to 25$ is a bit steep to me honestly …
Marin
Hey Marin,
Zwoptex is still free for use via the flash version and fully compatible with cocos2d though it lacks a few features the desktop version does.
http://www.zwoptexapp.com/flashversion/
In the future I plan on making a “Lightweight” version of Zwoptex that does not expire but has less features than the full version.
-Robert
Dell,
It looks like a problem in the plist. If you look in CCSpriteFrameCache.m at line 111, the assertion occurs when the plist format is not in the range 0..1.
Regarding Zwoptex & pricing: Making a tool like Zwoptex is a ton of work, so I think the developer deserves to get some $$ for their hard work. We’ve seen similar tools for Cocos2D that are paid as well, such as Particle Designer or LevelSVG for example. Hope it does well for you Robert!
Hi Ray,
Really great tutorials! Enjoying all of them. Im starting out with Cocos2D.
My question is about the code you used to setup the .h and .m files:
CCSprite *_bear;
This is creating an CCSprite object with a pointer to *_bear? Correct?
@synthesize bear = _bear;
Why is this needed? And also the other variables that start with _ (moveAction, walkAction)?
In dealloc, why dont you have self.moveAction = nil; ? You do have self.bear=nil and self.walkAction=nil.
Maybe you can just explain your logic here a little bit. Why are you assigning the _bear to bear in the implementation?
It would greatly help me understand what is going on. Your code looks very organized, I just want to learn to do things the right way from the very start.
Hi Ray,
Thank you for the tutorial!
It has helped me greatly.
I have a question about using multiple sprite sheets in the game.
Do I have to know exactly which sprite sheet I should directly attach my sprites to? Or does the sprite simply need to be one of the child in the hierarchy?
Meaning, can I have:
spriteSheet1 –> spriteSheet2 –> spriteObject
and spriteObject will be able to display frames in both spriteSheet1 and spriteSheet2?
Thank you.
@Rev: Regarding the underscore question, it’s a personal preference of mine, check my reply to @Jason in this tutorial for more details:
http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial
Regarding moveAction not being set to nil: You’re right, forgot to put that in there, heh!
@Tony: You have to add your sprite as a child of the CCSpriteSheet corresponding to the sprite sheet image it came from. So if you have a spritesheet image #1 with 50 blue sprites, and sprite sheet image #2 with 50 red sprites, and CCSpriteSheet #1 and #2, you would have to add a red sprite as a child of CCSpriteSheet #2.
CCSpriteSheets cannot be children of other CCSpriteSheets.
Let me know if that answers it for you!
Hi! I always visit your blog to see new tutorials on cocos2D because they are very clear to understand. One thing i’m trying to do now (and i’m losing A LOT of time trying to resolve this) is making a CCMenuItemSprite with an animated sprite. When I animate a sprite with sprite sheet, adding the animated sprite do CCMenuItemSprite causes an error that says it can’t render the sprite because i’m using sprite sheet. And when I make an animated sprite without sprite sheet, adding it to the CCMenuItemSprite doesn’t do nothing and the sprite doesn’t appear! I’m desperate trying to make a button with an animated sprite using cocos2D Menu class, but it seems it doesn’t work =(
The other way to resolve this would be by detecting the touch in the sprite area, but I think this could be harder then using CCMenu.
Can you give an answer to that, please? Thanks!
(sorry for my English, i’m brazilian)
Hi ray, fantastic tutorial yet AGAIN. Whenever I have an issue I always seem to find the solution on this site…
Unfortunately having my sprites as children of the spritesheet is causing a big problem. Beforehand they were children of my scrollable “map”, thus they all moved with it. Now they can’t be children of that map, any simple solutions come to mind?
Thanks for the help anyways!
@frase in rays tilemap sample the cctmxlayer is a child of a cclayer which is what is moved to scroll. Is that what you are doing? Or are you moving the cctmxlayer from the tnx map? What is your spritesheet’s parent?
Hi GeekAndDad. I don’t actually have a tmxLayer I just have a CCTMXTiledMap (I didn’t see a use for a tilemap layer).
Basically it was originally a sprite acting as a background map which the user can then add objects (containing sprites) onto. I then moved the map itself to scroll around, the objects were all children so they moved with it. I never moved the “helloworld” layer itself.
But now I need every sprite added to the map to be children of my spritesheet. I just read Ray’s tilemap tutorial for the first time, is my solution something to do with the fact that a CCTMXLayer is a subclass of CCSpriteSheet?
Thanks!
@Frase – not really. I haven’t done this (yet), but my guess is that if you add your spritesheet to the same layer that his tutorial adds the player to and then add your sprites made from the spritesheet to the spritesheet like in the spritesheet tutorial and I think it’ll ‘just work’. not 100%.
@Gabriel: Hm, interesting idea (making a menu sprite animated), something I hadn’t thought of doing myself!
I took a quick look at the CCMenu class, and it looks lke the easiest way for you to proceed would be just to create your own button object that derives from CCSprite, and handles ccTouchBegan/ended to implement the button behaviour you’re looking for. It isn’t that hard, and will probably be easier than trying to hack CCMenu :]
@Frase/@Dad: @Dad is correct, if you add the spritesheet as a child of the map, and then the sprites as children of the spritesheet, it should work – that’s what I’m doing in my latest app!
Made the adjustments, thanks guys!
Hey, This is a truly helpful tutorial.
I now can make a bear walk around as well, which is a huge feat considering i’m a complete novice programmer.
A friend of mine and myself are trying to make a game using sprites. I want the sprite to respond to an onscreen d-pad. The problem is, I’ll need the spritesheet to select exactly which sprites to use depending on the direction.
How can I make this possible?
Ray, I love what you have done here! This site is a wealth of information.
Could you take a moment and explain your coding?
What I’m interested in is this:
// Add inside the HelloWorld interface
CCSprite *_bear;
CCAction *_walkAction;
CCAction *_moveAction;
BOOL _moving;
I’m always looking for ways to improve my coding style and I’m not sure what your doing with the under line post-fix. eg. *_bear. I would love to learn the reason for this, benefits, etc.
Thank you so very much for your time.
RON
@Damore: Why not just set up four different animations – move up, down, left, right – and switch between the different animations as the user moves in different directions with the dpad?
@Ron: Ah yes I really should post this somewhere on a FAQ on the site heh :] But anyway, it’s a personal coding preference, check my response to @Jason in the following tutorial:
http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial
Hi Ray, great tutorial.
I had a question. Is there a way to find the number of frames in the plist. You have used a for loop with hardcoded value 8. But if we had a common function for multiple spritesheets, would it be possible to determine number of frames before hand.
Right now I am using :
`CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"%@%@00%02d.jpg",withSpriteSheet,forAction,i++]];
if(frame != nil) {
[animationFrames addObject:frame];
}
else{
numberOfFrames = [animationFrames count];
//NSLog(@”‘%@’ created with %d frames.”,forAction,numberOfFrames);
break;
}`
So I keep searching till i hit a dead end, and then i break. Though this approach is working for me right now, i dont know if this is the best way to do this.
@Nirbhay: In real apps/games what I like to do is keep an XML file that ties together the frame names for each animation, and have the app read that in.
For example here’s a snippet from my game Math Ninja:
That way I don’t have to hard-code anything into the app and it’s pretty easy to change.
@Ray : okay. I think i will too go for this approach.
But does my method of checking for a dead end cause any performance issues?
I have downloaded Zwoptex- 1.0.2.zip from zwoptex.com and then run the trial version but there is no export portion that contain on “save.jpg” and “save.plist”, what I have missing…
@Nirbhay: Doesn’t look like it, since you break out of the loop as soon as it can’t find a frame.
@Murad: It’s possible the interface may have changed in the latest version of Zwoptex. If anybody has the latest version and wouldn’t mind posting the latest instructions that would be great!
@Murad
You’ll want to look at the Publish/Publish Settings or File -> Export Texture / File -> Export Coordinates.
Either way will generate the .jpg and .plist. It was moved off the left side panel since it wasn’t specific to the Graphical Editor view.
Hi, I followed the tutorial exactly and I get the following warning when I build and run
exception ‘NSInternalInconsistencyException’, reason: ‘cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:’
Any idea what my problem could my?
Thanks in advance
@stef: I checked the cocos2D source, and it seems that the format tag may mean the format that the .plist from Zwoptex is saved in… my guess is Zwoptex may have changed the format of the .plist files, and you may be using an older version of Cocos2D… try using the latest version of Cocos2D and I bet it will work!
Yes that worked. I got cocos2d-iphone-0.99.5 and it worked perfectly.
I did get 2 warnings:
‘CCSpriteSheet’ is deprecated
‘spriteSheetWithFile:’ is deprecated
But I assume it’s nothing to worry about.
Thank you very much and I love your tutorials
@stef: In cocos2d 0.99.5, there’s a new class called SpriteBatchNode that you should use instead of SpriteSheet:
http://github.com/cocos2d/cocos2d-iphone/blob/release-0.99.5-beta/CHANGELOG
I haven’t had time to look into that yet, but when I do I’ll probably update this tutorial or write something new.
Thanks for the sprite sheet info.
If you want the sprite to change directions (left/right) you can use the scaleX, so you only need texture sprites in one direction.
self.scaleX = ( _dirIsLeft ) ? 1 : -1;
Here’s a way to animate without the use of actions might give you more control using a timer.
- (void) spinActionReady:(NSNumber*) numTimes {
if ( animTimer != nil ) {
[self stopAnimTimer];
}
gCurrentAction = SPIN_ACTION;
gIsSpinning = TRUE;
gSpinCnt = 0;
gSpinIterCnt = 0;
gNumSpinIters = [numTimes intValue];
[self setDisplayFrame:@"spinAround" index:0];
animTimer = [NSTimer scheduledTimerWithTimeInterval:0.06f target:self selector:@selector(DoSpin) userInfo:nil repeats:YES];
}
- (void) DoSpin {
[self setDisplayFrame:@"spinAround" index:gSpinCnt];
gSpinCnt++;
if ( gSpinCnt >= NUM_FRAMES_SPIN ) {
gSpinCnt = 0;
gSpinIterCnt++;
}
if ( gSpinIterCnt == gNumSpinIters ) {
[self stopAnimTimer];
gIsSpinning = FALSE;
[self setDisplayFrame:@"spinAround" index:0];
}
}
- (void) stopAnimTimer {
if ( animTimer == nil ) {
return;
}
[animTimer invalidate];
animTimer = nil;
}
I was having the same problem here is how I fixed it. It seems that there is an updating issue where cocos and Zwoptex havn’t gotten totally coordinated and can cause this problem. Hope this helps!
http://zwopple.com/blog/2010/07/08/zwoptex-integrating-1-0-jpg-plist-with-cocos2d/
B)
Sorry put wrong link that one explains the issue, here is the one explaining to change version of one or the other.
http://www.cocos2d-iphone.org/forum/topic/8505
Just confirming for you which way I converted. I updated to 99.5b and worked fine, got a few depreciated messages as noted above but like was said worked fine.
Check that, it seems that CCTimers are lightweight and more efficient than NSTimers. So replace them with the methods below.
// to start timer
[self schedule:@selector(DoSpin) interval:0.06f];
// to stop
[self unschedule::@selector(DoSpin);
Okay, with further testing, the CCTimer does not stop right away, so it is only good for game loops and the like where stopping on the dime is not critical.
The NSTimer will do fine, as the CCDirector uses it to run animations.
If you got an error like the following when you run the app.
*** Assertion failure in -[CCSpriteFrameCache addSpriteFramesWithDictionary:texture:], /Users/user_directory/Desktop/AnimBear/libs/cocos2d/CCSpriteFrameCache.m:111
2010-07-08 21:43:01.130 AnimBear-Upgraded[18054:207] *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘cocos2d: WARNING: format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:texture:’
To fix this error, open the file–”AnimBear.plist”, and set “metadata->format” to 1
metadata
format
1
size
{512, 1024}
Unfortunately, my bear doesn’t appear. What could be wrong? When I launch it I only see a black screen with those figures in bottom-left. Checking the .plist file, I noticed that those figures are different from what I saw In Ray’s screenshot. Could be the way I exported plist and jpg?
@Mark, @forkon, @Tim: Thanks so much for sharing the solution to these issues so others can benefit!
@Alex: I’m not sure but it could be a version incompatability between the version of Zwoptex & Cocos2D that you’re using. Safest bet is to use the latest of each.
No problem, it’s part of the experience! Thank you for all your great tutorials too.
Hi Ray!!
man you are doing awesome work…
really hats off for you & your Work :)
i am currently animating different things using SpriteSheets but the problem i am facing is the excess of memory usage… The spriteSheets work fine if there are only few sprites (with different jpgs & plists) to be animated but as the number of sprites on screen increases proportionally the memory increases.
the method i am using for the animation is same as you have explained in the above tutorial..
so I’ll be pleased if you give me the solution to my problem..
@Naqi: Thanks for the kind words!
Regarding performance, the first place I’d recommend is to check out the cocos2d best practices’s guide, which contains a bunch of performance tips:
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:best_practices
Another good place to check is the PerformanceSpriteTest that comes with Cocos2D.
On performance, I found this to be helpful too.
http://allseeing-i.com/Performance-tips-for-Cocos2d-for-iPhone
@naqi: The better approach is if u use same sprite sheet for diff animations, if your objects will be of same size then their would not extra headache of plists, you would be able to do your work with only a single plist.
The second option is to use CCTexture, you will be using separate images for animations loading one at time but it will obviously increase processing work.
@nadeem
the first option of uniforming the objects is quite hard from me to use as the frames vary in sizes..
while considering the second can you give me any sample code or tutorial where i can learn that how animate using CCTextures as i am a newbie to this arena of Cocos2D.
@Ray
my problem is related to memory not the performance.. if you could tell me how to handle multiple animation with minimum memory usage using spriteSheets..
Hi,
Great tutorial, as always :D
I have a question, I tried to call the RunAction in ccTouchBegan instead of ccTouchEnded, and for some weird reason that causes my program to crash. Is there something I missed? I followed the rest of the stuff, up until the ccTouches part.
Thanks.
@Tim: Yeah that is a great article, thanks for sharing!
@Naqi: Like @Nadeem said (thanks for helping out btw!), probably the largest source of memory usage is going to be your images, so if you can reduce the number/sizes of the images you’re loading by combining different animations into the same sprite sheet, you’ll get some benefits there.
Also, like the guide Tim suggested points out, make sure you’re not including unnecessary animation frames when you could flip the frames, and consider using other pixel formats for images that don’t necessarily have to be at the highest quality (such as backgrounds, etc.)
@Hsaio: Hello again! :] I don’t know of any reason why moving the code from ccTouchBegan rather than ccTouchEnded would cause the program to crash. In fact I just downloaded the sample project and copied/pasted the code from ccTouchEnded to ccTouchBegan and things seemed to work OK. Maybe try comparing your code to the sample project?
@Ray
thanks for the solution :]
Hi Ray,
Thank you for your excellent tutorial! You are the best
instructor I have ever known! I would suggest you to setup a cyber course!
I wonder would you mind sharing some codes to show a loading status when start any games for preloading resources? I got something but don’t know how to use it.
Thanks in advance!
GREAT TUTORIALS :) KEEP THEM COMING!!!
I have a question about this:
@synthesize bear = _bear;
@synthesize moveAction = _moveAction;
@synthesize walkAction = _walkAction;
why making a name equal to the same with an _??
Is there a main reason for this?
Moreover i used ur code in a game of mine but i get an error! I have a spritesheet and im trying to make the action when a key is pressed. But the method doesnt find the CCAction, CCAnimation etc and got a bad access error and dealocation etc. It only works when i remove these bit of code from init method and paste it on the same method as the code for the button! Any advice on these would be helpful :)
@Ray, sorry it was a silly mistake I did, works fine now. Thanks so much for the tutorials, you are awesome :D
@Kyriakos Kafas: Regarding the underscore question, check Ray’s reply to @Jason in this tutorial for more details:
http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial
@Jiaren: Thanks for the kind words! For loading status, you might want to check out the Tom the Turret sample that comes with Cocos2D for an example of adding a loading screen:
http://www.raywenderlich.com/1345/tom-the-turret
@Hsiao: Awesome, glad you got it working!
@Naqi: Thanks for helping out Kyriakos! I definitely have to write a tutorial FAQ on that soon :]
Thanks for the tutorials but I’ve run into a problem. I’m trying to animate the monsters from your other tutorial on creating a basic shooting game.
What I did was set up the actions the same way you did in this tutorial. Then in the addMonsters method I set it to run the animation action before the [_spriteSheet addChild:monster] (modified the code from self to spritesheet). However, it seems that every monster is running off the exact same instance. So for example, when the monster is shot and I have it stop the animation action, every other animation also stops. When multiple monsters are on the screen at the same time, the newer spawning monsters keep spawning at a faster framerate because it seems its running both the action from the previous spawned monster then the action again from the new spawn.
Eventually it crashes from the same actions running through all the monsters simultaneously. Any ideas on what could be causing this? I also tried setting the CCAction to id actionAnim in the actions part of addMonster but still got the same problem.
Hmm, I got it to work by instead creating the array and animation each time addMonster is run instead of creating it in the init. Just wondering now if there is a more efficient way instead of creating a new array every time an enemy is spawned.
Seems when you create animations in init you have to be much more careful as to not run the same animation action twice for the same object or it will crash.
hey ray
what do i do If i want to add the frames dynamically?
I dynamically get a image and i rotate the image and get 3 more images, but how do i add this as Sprite frames?
@jpang: Yeah, CCActions are not made to be reusable. So you’ll have to create the CCAnimation each time. However, you should be able to create the array of animation frames just once, and pass that to your CCAnimation object each time. Check out a good discussion of this here:
http://www.cocos2d-iphone.org/forum/topic/6630
@Bk: You can do that, but you’re going to have to dig around the Cocos2D source a bit to come up with a solution. CCSpriteFrame has a frameWithTexture object you can use to create sprite frames from an arbitrary CCTexture2D. You can then add those to an array and create a CCAnimation based on that. Note that you’ll lose the performance benefits of using a sprite sheet if you go this route, unless you compose your images into a single image and create a sprite sheet dynamically as well.
@Ray: Thanks! I got it to work. Also another important thing I found is
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
should be added in dealloc to prevent memory leaks according to: http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:animation#using_sprite_sheets
Hi Ray,
Just wonder have you got any idea to keep device screen active while play a game that controlled by accelerometer? I couldn’t find such topic from web.
Thanks in advance.
Jiaren
@Jiaren –
You could disable the idle timer to keep your app awake. In your game’s init put this line [UIApplication sharedApplication].idleTimerDisabled = YES;
Or you could fire an nstimer every 10 secs or so and play a sound, it’s said to keep the app awake as well.
Any ideas how to remove spriteSheet is deprecated warning? I have no idea why I am getting this warning, I have another project and I am using the same way to animate in both however I don’t get this warning in other project.
Any ideas how it can be removed?
Try using CCSpriteSheet in the latest version.
Is there a simple way to change the TileMap tutorial to use this tutorial to move the Ninja with an animation?
Ray — you might be growing tired of hearing that kinda stuff about your tutorials. Here’s the millionth:
YOU TOTALLY ROCK!!
Thanks much!
- Anderson
I actually messed around with the TileMap code and added animation of a man I made and finally got it to work. I only have the man walk the distance of 1 tile like the ninja because not sure how to check for collide for a long distance. Also not sure how to make viewpoint to follow until man is done moving and it makes it jumpy. It is cool to have man walk on tilemap though.
Great tutorial Ray!
I had a problem with compiling, I don’t know the reason but the value for “format” on my metadata plist was 2 instead of 1 and it was causing the whole program to crash at startup. Anyone know the reasoning behind this?
@jpang: Cool, thanks for the heads up!
@Tim: Thanks for helping jiaren and Shuwee!
@Shuwee: In the latest version of Cocos2D CCSpriteSheet has been renamed to CCBatchNode, hence the warning. Discussion here:
http://www.cocos2d-iphone.org/forum/topic/7917
@Anderson: Lol thanks glad you like the tutorials! :]
@Stephen: Cool glad to hear you’re making progress!
@den: The plist format Zwoptex uses changed in a recent version of Zwoptex, so you have to make sure the version of Cocos2D and Zwoptex are compatible. Easiest way is to make sure you have the latest version of both.
I am having trouble. I want to have a walking man animation then when stop have a standing man image, but I can’t find anything about how to do this and to switch back and forth between at appropriate time. Anything I find on textures etc doesn’t seem to work. Can someone point me to example? The most frustrating thing about Cocos2d is the lack of a detailed manual.
Hi
I was recommended to use this to have both standard and retina display graphics and it works.
if ([UIScreen instancesRespondToSelector:@selector(scale)])
[director setContentScaleFactor:[[UIScreen mainScreen] scale]];
However after making this animated sprite with your tutorial (works great by the way) it shows up but it doesn’t scale up when on an iphone 4. Why do you think this might be? Or what can I do?
Thanks!
Can I use multiple sprite sheets for animating objects on the same layer?
Please, help me understand. I do not see animated bear. I get error and in console I always see WARNING: original Width/Height not found on the CCSpriteFrame. AnchorPoint won’t work as expected. Regenerate the .plist.
@Stephen: Yeah unfortunately there isn’t a lot of good documentation out on Cocos2D yet, but I know a couple guys are working on books.
Regarding switching animations, you can simply create two different animation actions like we do in steps 1-5 in the tutorial above, and store them in different variables (such as _walkAction and _standingAction). Then in bearMoveEnded, after you stop the _walkAction, you can start the _standingAction, and when you run the _walkAction you can stop the _standingAction.
@Josh: Just in case you haven’t heard, a new version of Cocos2D recently came out (0.99.5-beta) with improved retina display support, and there’s a great guide with a lot of information about how to develop retina-display games here:
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:how_to_develop_retinadisplay_games_in_cocos2d
@Varun: Yes, you can.
@dyulur: Did you try the sample project – does that work OK for you? If that works but your project does not, double check you have the latest version of Zwoptex and Cocos2d.
_walkAction , _standingAction. Duh! Why didn’t I think of that? If you know what the titles of books might be could you post sometime? I already have one on order from Amazon but it is not due until January.
Thanks for all your help.
Apress have a good Cocos2D book. You can buy the alpha book so you can get it before release as chapters are written. 11 available so far and is really good.
http://www.learn-cocos2d.com/
Hi Ray,
Firstly thanks for your time and effort with these great tutorials.
I would like to ask if you have ever played with the blend functions within cocos2d. Currently I keep all sprites for one level on a spritesheet. What I want is for the sprite to flash when hit. The problem is that when I use the blend function on one of the sprites nothing happens. If I apply the blend function to the spritesheet then the sprite will flash as required. The problem is that all the sprites on the spritesheet flash also :(
Example (for sprite):-
id actionReset = [CCCallFuncN actionWithTarget:self
selector:@selector(resetVulnerability:)];
[target setBlendFunc: (ccBlendFunc) { GL_SRC_ALPHA, GL_ONE }];
// Move projectile to actual endpoint
[target runAction:[CCSequence actions:
[CCDelayTime actionWithDuration:0.4],
actionReset,
nil]];
-(void)resetVulnerability:(id)sender {
Ship *node = (Ship *)sender;
[node setBlendFunc: (ccBlendFunc) { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA }];
node._invunerable = NO;
}
Any help would be much appreciated.
Regards
Tim
@Ray
Thank very much, Ray. You are absolutely right. My version of cocos2d is older than Zwoptex version.
Thanks so much Ray! Your tutorials really help me out! I love working in Cocos2D! I really appreciate your tutorials and your help. Hopefully, I’ll have my first game out by December!
@Tim: Good question! I actually haven’t played with that myself, but if you find the solution please post it here so others can benefit :]
@dyulyur: Awesome glad you got it working!
@Tamara: Thanks, and best of luck with your game! :]
Zwopple released Zwoptex version 1.1b4 and it is the only one that works for me with Xcode 3.2.3. I still had to rename a few properties that weren’t matching up like “sourceSize” and spriteSourceSize” for example. I am just glad they came out with that version, because the other ones kept crashing on me. :-)
Hi I’m brazilian and a like to say… Great tutorial!!! Im building my game with cocos2D and your tutorials are helping me a lot!
Thanks!
@Tamara: Good to know, thanks for sharing the info for everyone else!
@Antonio: Glad the tutorials came in handy, and and good luck with your game! :]
Hi Ray, thanks for all your tutorials, please keep on the good works… As a distinguished noob++++, I have learnt a lot about cocos2d in a very short time.
However I have problem with a project I am trying to bring to life. Having gone through your sprite animation tutorial, I have a question to ask about how to go about carrying out animations manually(touches)where the user has to use his or her fingers to move a particular sprite and the sprite moves with the finger until the finger is released or lifted which lets go of the object…a classic example would be to imagine these 3 steps involved in shooting an arrow from a bow:
step 1- the arrow is placed on the string of the bow.
step 2- the end of the arrow is touched and dragged backwards which makes the string and the arrow to move too depending on the distance travelled by the finger.
step 3- will be the release of the finger by lifting the finger off the screen of the iphone thus making the string to spring back to its position and the arrow sent in flight or shot taking into consideration the angle which the arrow and bow were positioned before release.
These steps and the physics involved looks very complex to me. The only thing I have been able to think of is using touches moved and looked at the velocity and distance equations like
dt = 1.0/60.0;
v += g*dt;
p += v*dt;
but I have no idea where to go from there. Can you help me out with these ? can it be animated in this form but manually?
Hi Ray,
Thanks a lot for your great tutorial!
I have a typical question about the character animation update.
How can I change/update the walking animation during the walking action of the bear? In more details, I want to draw a bezier line, and let the bear walk along that bezier line (cocos2D has the bezierTo, bezierBy actions). During the bear’s walking action, the bear may face different directions (e.g. up, down, left, right, upright, upleft, downright, downleft). I may want to set different animations for the bear for its different walking directions.
I know this sounds kind of complex, since the bear’s walking direction keeps changing if it walks along a bezier curve. But, I think it is a typical question.
In fact, I try to make the character looks similar to the ones in some 45-degree-angle-camera games such as StarCraft I, Diablo I/II.
Have some hints to do the job? Register a CCNode update function to keep monitor the walking direction, and change/update the animations in some way?
Regards,
Ken
Hey Ray,
great tutorials, but i wanted to let you know, incase you weren’t aware, the class CCSpriteSheet has been deprecated and it is now known as CCSpriteBatchNode. If you are to use CCSpriteSheet i think it might still work, but you’ll get compiler warnings.
Ken,
I do a similiar thing with my game. You could define your bezier actions and a custom function that is called before each “Move action” and place them all in a sequence. I also utilise flipX, flipY to facilitate this. Not on main machine with code, but your sequence could be (customFunc, bez1, customFunc, bez2, etc…). you could change the animation in the customFunc, or utilise flipX, flipY to same space.
Hope this helps.
Regards
Tim
Started my iPhone Game Dev study from
http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial
and now I am here….
thanks a lot for all your tutorials :-)
Keep rocking :)
Ray – Thanks for an excellent tutorial!
I followed all steps, three times and I get no warning, no errors, but also no bear :-(
Ideas?
Thanks!
Hanaan
Hi Ray,
I have the same problem with Hanaan Rosenthal.
I think the problem is the version of Zwoptex (1.1.6).
After I created my own plist, it is totally different from yours. In your given plist, the names of keys are frame, offset, sourceColorRect, and sourceSize. But in the plist created by Zwoptex 1.1.6, the names are spriteColorRect, spriteOffset, spriteSize, spriteSourceSize, spriteTrimmed, textureRect, and textureRotated. And also, the format is 3. (3 will generate error message, so I change it to 1.)
Thanks for your effort.
Hi Ray,
I find a solution.
replace the names as follow:
spriteColorRect -> sourceColorRect
spriteOffset -> offset
spriteSourceSize -> sourceSize
textureRect -> frame
Some keys I don’t know:
spriteTrimmed
textureRotated
Thanks for your help.
Regards,
TM
@TM
I use the zwoptex flash version @
http://zwoptexapp.com/flashversion
and cocos2d 0.99.5 and everything works fine… :)
It does seem that the newest version of the Zwoptex app names its .plist different than the current Cocos2d build(99.5-rc0).
As @TM mentioned, using the Flash version still has the same naming convention and will allow the the .plist to be read properly. If I can figure all these animations out myself, I may try writing a small updated tutorial to help out.
Just going to chime in…
What “Coordiantes Format” are you using in Zwoptex 1.1.6 with cocos2d 99.5-rc0 that doesn’t work anymore?
Cheers,
Robert
@Robert, after asking me this, I went and checked. I now see that I was choosing the wrong coordinate format. So, that was it. Nothing wrong with your app afterall, just my own ignorance. :)
Thank you for the enlightenment, and thank you for the great utility!
@Ty Boo
No worries I know that it can be confusing with many different coordinates formats in the tool. I chose to make a specific cocos2d one that will always be compatible with cocos2d as not to break user’s sprite sheets!
@Etteba: What you are describing sounds like a great case to use Box2D. Box2D is a physics simulation engine that can simulate objects being affected by forces such as gravity, impulses, or collisions. For your bow and arrow example, you could track the difference between the start of the drag and the end of the drag, and apply an impulse to launch an arrow through the air, and Box2D would handle the rest (the gravity bringing the arrow back to the earth, the effects of the arrow colliding with objects, etc.)
I have a couple tutorials on Box2D that may be helpful, here’s the first one:
http://www.raywenderlich.com/457/intro-to-box2d-with-cocos2d-tutorial-bouncing-balls
@Timothy: Thanks for helping out @Ken! Another option would be to have an update method called each frame that compares the old sprite position to the new position, and calculates the angle the bear is currently facing, and switches the animation if necessary.
@Kyle: Thanks! I was aware of that, but hadn’t had time to update the project yet. I just updated the post and sample code to note that, thanks for the reminder! :]
@Saiyasodharan: Very cool, best of luck with your iPhone game making! :]
@Hannan: Did you compare your code to the sample project? I just gave the sample project a shot and it seems to work OK.
@Ty, @Robert, @Saiyasodharan: Thanks for helping sort out people’s questions with Zwoptex!
hi ray,
i am using progress timer in my project.
it works fine.
am using this code for progresstimer.
http://www.cocos2d-iphone.org/forum/topic/10781#post-62125
whan i touch the screen it will stop and i want that stopped percentage in timer.(calculating velocity) . i used some code but it will terminatig my app
@srinivas: This question isn’t related to Animations and Sprite Sheets, please let’s keep the discussion focused here.
Hi Ray – maybe this is not right place for this question, but …
I know that I can edit the image, and create separate images, and than pack them into “texture pack” like you did in above example.
But I have an image (let’s say square 3×3 with numbers 123456789), and I want to multiple create Sprites from this image.
I would like to get 9 sprites – on each different number.
Is this possible – if yes – please help me with some kind of cocos2d resource…
And – best of all – your blog is “the” best!
@jaboicnik: Thanks for the kind words!
Yeas, you can create as many sprites as you’d like from a sprite sheet. It would be something like this:
Hope this helps!
Ray – Selected Cocos2d format in Zwoptec and works like a charm!
Thanks.
@Hanaan: w00t glad you got it working, and thanks for posting your solution so anyone else who runs into the same problem can benefit! :]
I know this turned a bit into a Zwoptex forum, but using Zwop is at the heart of it so I guess it’s OK.
I’m having issues again with Zwop’s format.
The first time I chose ‘Cocos2d’ from the “coordinates format” in preferences, I got a correct, working format where the “Frames” dictionary looks like this:
x
0
y
0
width
123
height
123
offsetX
0
offsetY
-0
originalWidth
123
originalHeight
123
After, I started getting the following, which doesn’t work:
aliases
spriteColorRect
{{4, 1}, {33, 41}}
spriteOffset
{0, 0}
spriteSize
{43, 43}
spriteSourceSize
{43, 43}
spriteTrimmed
textureRect
{{86, 43}, {43, 43}}
textureRotated
I can’t seem to be able to get back to the setting where Zwop exports working coordinates regardless of what I select in Preferences…
I’m using the latest version 1.1.6 (30)
Thanks!
Hanaan
Hi I have a question about cleaning up the sprite.
It is about actions in general but since animation is using it too, I thought it might be appropriate to ask it here.
Do I need to do “stopAllActions” on a sprite before I release it?
I am asking this because I have a Sprite with some children setup, and some might be running its own actions.
Wondering if I can simply remove and release the parent sprite without having to worry about actions of the children sprites.
Thank you
@Hanaan: Not sure, maybe try emailing Zwoptex support?
http://www.zwoptexapp.com/support
@theone0621: Good question. I checked into the source, and when you call removeFromParentAndCleanup:YES on a sprite, one of the things that happens is all the actions get stopped with stopAllActions automatically – so you don’t need to worry about it!
Thanks, Ray – it was just Zwop funkiness. You have to click Publish Settings in the window and choose Flash format…
Q regarding the actual animation:
I have a sequence of images of a person running. During the game, he has to run faster or slower.
What would be the best method of speeding up and slowing down rate?
I’m assuming it would be done by changing the delay, which I can’t do while the animation is running.
If so – how do I:
1. Stop the animation
2. Change the delay
3. Restart the animation
I can also create 3 variations with different delays and switch between them, but can’t figure out how.
Thanks for your (anticipated, yet not taken-for-granted) response. Your contribution to the Cocos2d developer community is highly appreciated!
Is there any way to know which sprite image is shown in the current frame?
Thanks,
TM
@Hanaan: You’re right, you’ll have to stop the animation, change the delay, and re-run. Check out this thread for more info:
http://www.cocos2d-iphone.org/forum/topic/5056
@TM: One way is you can access the texture property from the sprite, and compare it to the textures for your various sprite frames to check.
hi, ray. i’ve been learning from our tutorial from the beginning! BEST COCOS2D TUTORIAL EVER!
right now i’m trying to put two of your tutorials together, which is the one that spawn weak and strong monsters and this tutorial.
from this tutorial, i can animate the bear, but i can’t figure the way to animate the sprite from another class (e.g. monster.m from your old tutorial).
Thank you^^
I never saw an animation class that has a worser structure than this one …
Nice tut btw
@wince: Lol thanks man! Regarding your question, what is the exact problem you’re having? You should be able to follow a similar process:
1) Create a SpriteBatchNode and add it to your layer
2) Load the spriteFrames into the spriteFrameCache
3) Create an animation object for your monster and run a CCAnimate action on the monster
Let me know where you’re getting stuck!
@abcdefg: What don’t you like about the animation class structure?
Thanks for all the hard work on these tutorials.
Right now you touch somewhere on the screen and the bear moves to that point.
How would you animate the bear by touching just the bear and having him/her move? So touch the bear and he/she moves up/down, left/right whatever. The bear would only move if you touch it.
hey Ray, trying to learn to do this animation thing. My problem is it’s giving me the error of “CCSpriteBatchNode undeclared” It only recognises the old CCSpriteSheet. How do I convert it to latest code? I downloaded Xcode 3.2.5 from the Apple website and got cocos2d 0.99.4
I downloaded your sample and it works fine in simulator and device so I’m not sure what’s going on.
thanks
@Mark: I think CCSpriteBatchNode is available only from cocos2d 0.99.5. in 0.99.4, u can only use the CCSpriteSheet
that makes sense. The only reason I don’t want to download 0.99.5 is because the site says it’s unstable. I’ll just use CCSPriteSheet instead and see how that goes
hm…. now it won’t recognise “animationWithFrames” it has “animationWithName” which sounds like you have you have put each frame individually :\
i don’t know is this discuss above in comments or not but one little thing u missed in your tutorial. even its very little but it took aprox a day for me to find out the issue.
When you save a plist file from zwoptex you should set cocos2d file format by default it zwoptex generic.
-Usman
phew finally got there after a few hurdles :)
Hi Ray!
First of all your tutorials great. The best in web.
I have got some problem about creating plist file I think. I downloaded your source and run it and it ran fine. but When I tried to do whole steps by my self I got just a black screen. No animation was on it.
I open up the console to check out what is wrong and saw a message such as ” originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won’t work as expected. Regenerate the .plist”.
Did I do something wrog wile creating the plist file?
if you have any answer for me I ll be appreciate..
Thank you.
Umm.. Sorry I did not read the comments. Now I read them and I think I can solve the problem by digging around on zpowtex.
Thanks anyway!!
Hi All,
I think Usman know you are using cocos2d, aren’t you? Don’t put your responsibility on other’s shoulder.
Besides, I am appreciated Ray’s contribution in iphone development.
Be honest, I learnt a lot in his tutorial and they are the best I’ve ever found online.
Hope Ray will keep going to teach us more.
Thank you so much.
Best Regards,
TM
@MarkW – Can you fill us in? I’m using the same version as you and getting the same errors. Can you explain what you did to get it to work?
I was using zpowtex 1.1.6 and I think it does not support the cocos2d version I have. But I solve the problem by using flash version of zpowtex on web.
Now it works fine.
Thanks for these great tutorials Ray.
I just released Zwoptex 1.5a1 anyone that is just starting up development I’d recommend using it as it has some great new features that will work well with cocos2d.
For existing users it should only be another week or two until you can use all the features without a painful data migration.
-Robert
Hi everyone!..
Here is another question.
Can I use animations over Box2d? for instance I have a circle body and I made an animation. I put this animation over the body but when I put it on, my body lost its phisical attributes. It is not moving. just animation takes effect.
Anyone knows how to solve it?
Thanks.
Omer Farruk.
Hey Ray. Thanks for the tutorials. I have a quick question. If I understood correctly, you said we can’t do z ordering with with sprites from different sprite sheets. In other words, I can’t draw a sprite from sprite sheet “A” in front of a sprite from sprite sheet “B” and also have a sprite from sprite sheet “A” behind the one from sprite sheet “B” because drawing of all sprites of a given sprite sheet is done in one call.
Here is my question. If I’m using the same sprite sheet to draw sprites in three different layers, for example, bg, main, and foreground, does it draw all three layers using the same call, or one for each?
Hi Ray:
First I want to thank you for this blog, you have teached me a lot of thing although I am just starting in this world.
I have a question for you, I read the example and I made my own implementation, a lot similar to yours but with little changes. In the “bearMoveEnded” event that is launched after de movement of the sprite ended I wrote this line:
self.bear = [CCSprite spriteWithSpriteFrameName: @"someImageInTheSpriteSheet.jpg"];
What I am trying to do is to put another image when the character is not moving, but if I do it then the sprite stops moving forever. It listen the touch events and all of that but the sprite doesn’t move anymore.
Thanks for any help you can give me!!
:D
@demetriusb: I wrote a tutorial recently on moving sprites with touches that may help:
http://www.raywenderlich.com/2343/how-to-drag-and-drop-sprites-with-cocos2d
@MarkW: Yeah I updated this tutorial for the most recent version of Cocos2D a little while back, and there were some naming differences between the two.
@Muhammad: Thanks for pointing this out, this must have changed since I wrote the article. I’ve updated the post to hopefully prevent others from running into the same problem, thanks again!
@TM: Thanks for the kind words and support!
@Mike: Double check your format is set to Cocos2D, and if all else fails use the Flash version of Zwoptex.
@Robert: Yep the new features look great!
@Omer: You should be able to run an animation on a sprite that is associated with a Box2D body. If you’re having troubles, make sure that you’re updating your sprite’s position every frame based on the Box2D body’s position.
@MR2: That is correct. AFAIK, if you draw sprites in 3 different layers, that is 3 different draw calls, since you’d have a different SpriteBatchNode in each layer, and that’s where the batching of the draw calls occurs.
@V3NOM: An better way is just to change the current display frame for the sprite. So it would be something like:
Assuming you’ve loaded your sprite frames from a sprite sheet.
my cocos2d project doesnot contain CCSpriteBatchNode.h file
y so?? what is the problem?
and i tried to add it manually but i cant find that file in my finder also
Ray:
Thank you so much, it did work perfect!!
Can you tell me why does the other line crashes everything? I used it based in the “init” method where you used to initialize the sprite:
CGSize winSize = [CCDirector sharedDirector].winSize;
self.bear = [CCSprite spriteWithSpriteFrameName:@"bear1.jpg"];
_bear.position = ccp(winSize.width/2, winSize.height/2);
self.walkAction = [CCRepeatForever actionWithAction:
[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]];
[_bear runAction:_walkAction];
[spriteSheet addChild:_bear];
Is the second line in the 5 numeral in the first section of this tutorial in case that the code above ended unreadable.
Thanks again! =)
@prashant You have to download the cocos2D 0.99.5 rc1 from here: http://www.cocos2d-iphone.org/download
It was renamed in this new version of the framework, it used to be called CCSpriteSheet
Another thanks Ray, I almost gave on on cocos2d at a point but your tutorial made it understandable and interesting again.
Hey All,
Zwoptex 1.5 alpha’s have been released it brings loads of new features to Zwoptex that makes creating animations easier than ever. It’s only available through my blog right now but will be available via the automatic updater soon.
Read more about the alpha series on my blog:
http://zwopple.com/
Cheers,
Robert
Hi Ray,
Fantastic tutorial, as usual.
Something that I think would be incredibly useful would be how to have an animated sprite that is a subclass of CCSprite.
For instance in part three of the ninja tutorial, we make a monster.h and .m. If the sprite in there was animated it would be soooo helpful.
I know, us end users, we just want want want.
Just a suggestion.
Thanks for all the help so far.