How To Use Animations and Sprite Sheets in Cocos2D
2011-03-10 11:48
381 查看
How To Use Animations and Sprite Sheets in Cocos2D
Like this post? Follow me on Twitter!Smoky says: Only you can start this bear!
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 fromzwoptexapp.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 .png” in the Export section, and save the Png to the resources folder of your project as “AnimBear.png”. 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.png 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; |
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; } |
1) Cache the sprite frames and texture
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: @"AnimBear.plist"]; |
Looks for an image with the same name as the passed-in property list, but ending with “.png” instead, and loads that file into the shared CCTextureCache (in our case, AnimBear.png).
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.png"]; [self addChild:spriteSheet]; |
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.png", i]]]; } |
4) Create the animation object
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f]; |
5) Create the sprite and run the animation action
CGSize winSize = [CCDirector sharedDirector].winSize; self.bear = [CCSprite spriteWithSpriteFrameName:@"bear1.png"]; _bear.position = ccp(winSize.width/2, winSize.height/2); self.walkAction = [CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]]; [_bear runAction:_walkAction]; [spriteSheet addChild:_bear]; |
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; } |
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]; |
2) Set the desired velocity
float bearVelocity = 480.0/3.0; |
3) Figure out the amount moved in X and Y
CGPoint moveDifference = ccpSub(touchLocation, _bear.position); |
4) Figure out the actual length moved
float distanceToMove = ccpLength(moveDifference); |
5) Figure out how long it will take to move
float moveDuration = distanceToMove / bearVelocity; |
6) Flip the animation if necessary
if (moveDifference.x < 0) { _bear.flipX = NO; } else { _bear.flipX = YES; } |
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; |
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
Tags: cocos2D, iPhone, sample code, tutorial
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
http://www.raywenderlich.com/1271/how-to-use-animations-and-sprite-sheets-in-cocos2d
相关文章推荐
- How to Use Animations and Sprite Sheets in Cocos2D 2.X
- Spring Form Tags - How to use Text Box, Radio Button, Check Box and Drop Down List in Spring
- How to Setup and Use Github in Ubuntu
- How to Access and Use the Windows Hosts File in Windows 7 and Vista
- How to use a 32bit Oracle11_g client in 64 win system and not conflict with sqldeveloper 64 bit tool
- How to Manage and Use LVM (Logical Volume Management) in Ubuntu In our previous article we told you
- How to use Comparator and Comparable in Java? With example
- How to use git in general and bitbucket in particular
- ACC97: How to Use Percent, Plus, and Caret Symbols in ASP Forms
- How to use write and run MapReduce in eclipse on windows.
- How to use HttpWebRequest and HttpWebResponse in .NET
- How to use, monitor, and disable transparent hugepages in Red Hat Enterprise Linux 6
- How To Use ADO.NET to Retrieve and Modify Records in an Excel Workbook With Visual Basic .NET(利用Ado.net导出到Excel)
- How to use ConcurrentHashMap in Java - Example Tutorial and Working
- How to use $http and $resource in Angular JS
- How to use *args and **kwargs in Python
- How to use QToolBar and QToolButton in Qt
- 如何在python中使用*args,**kwargs (How to use *args and **kwargs in Python)
- how to save a c++ object in java object and use it
- How to create a DLL library in C and then use it with C#