I must have spent over a week coming up with a good solution for this. The effect I was after was a scrollable menu for my game, similar to Angry Birds where the user can flip between levels but also see a preview of the previous/next page on either end of the screen. I came across Nate Murray’s excellent UIScrollView solution but it wasn’t quite what I was looking for and using UIScrollView seemed like too much of an overhead. I needed something simple, preferably wrapped up in a single class.
After searching various community forums I finally came across DK101′s solution which was exactly what I was looking for. A simple CCLayer subclass that would allow me to create an array of CCLayers then add whatever I wanted to it then add the whole lot to my scene. Simple. You are able to add anything you can add to a CCLayer – so a label, menu, image etc. It will all work nicely.
I ended up making a few modifications to it like updating it to work with Cocos2d 0.99.5 and adding the option to set the width of the screens for the Angry Birds style preview effect. There was also an issue with the touch delegate on subsequent scenes. I have put my changes up on Github. Here’s a sample:
To use it in your project:
1. add both files to your project
2. in your scene import CCScrollLayer.h
3. in your scene’s init method construct each layer and pass it to the CCScrollLayer class:
I struggled with this as a n00b in Cocos2d and I finally figured it out so I wanted to share it here in case someone else runs into the same challenge. You may or may not be aware of sprite sheets in traditional 2D games and in CSS where you combine a series of images into a single image, then use x/y offsets to expose the bits of the image you want. Cocos2d makes this process very easy but I wish it was documented better. I’m new to this so please let me know if you think there’s a better way to do it.
This example assumes you know your way around an XCode project and know the basics of Objective-C and Cocos2d. If not, there are plenty of good tutorials around. See my previous post for some useful links. Also, I’m using Cocos2d 0.99.5 so some of this syntax may not work on older versions.
Now, onto the tutorial:
The first thing you want to do is get yourself a sprite sheet and associated plist file. Cocos2d has a bunch of these in its examples folder but you can also make your own using the excellent Zwoptex app. The app will let you add a bunch of images and it will then re-arrange them, export a single image and also generate a plist file containing all the coordinates. This means you won’t have to mess around with x/y pixels to get everything lined up.
Important: make sure in the Zwoptex publish settings you select Cocos2d for the coordinates format.
Once you have added the two files to your project, you can load all the individual frames in the cache and use them however you like.
1
2
// load the plist file into the frame cache[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"mysprite.plist"];
That’s it. Zwoptex will give each frame its own name. Look inside the plist file to see what they are called. These will most likely be the original file names of the images before you combined them into one.
Now that the frames are in the cache, we can create and display them as individual sprites like this
You can add any of the other frames to the scene the same way, just make sure you use the correct frame name like dude2.png, dude3.png etc. Again, if you’re not sure what the names are, just open the plist and look at the frames node.
Now that we have all our frames ready to use, we can do some cool things with it like animate them or use them as rollover effects for menu buttons. In the game I’m currently developing I wanted the character to blink from time to time. So I used two sprite images, one with the character’s eyes open and one with its eyes shut. You can then create a sequence and animate them like this:
// Load sprite plist file[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"dude_blinking.plist"];
// Create a blank array to store all the frames NSMutableArray*blinkAnimFrames =[NSMutableArray array];
// Add the frames 3 times. One with eyes open, one shut and one open again [blinkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"dude_open.png"]]];
[blinkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"dude_shut.png"]]];
[blinkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"dude_open.png"]]];
// Create a 3-frame animation using the array and use 0.2 seconds delay between each frame
CCAnimation *blinkanimation =[CCAnimation animationWithName:@"blinker" frames:blinkAnimFrames];
CCAnimate *blink =[CCAnimate actionWithDuration:0.2f animation:animation restoreOriginalFrame:NO];
// Now create the blinking action sequence
CCAction *blinkAction =[CCRepeatForever actionWithAction:[CCSequence actions:[CCDelayTime actionWithDuration:2.0f],
blink,
[CCDelayTime actionWithDuration:3.0f],
blink,
[CCDelayTime actionWithDuration:0.2f],
blink,
[CCDelayTime actionWithDuration:2.0f],
nil]];
// Add the actual sprite (first frame from cache) to the scene
CCSprite *dude =[CCSprite spriteWithSpriteFrameName:@"dude_open.png"];
[self addChild: dude];
// Finally, run the blinking animation[dude runAction: blinkAction];
If you study the blinkAction carefully, you’ll see we have just created an endless loop that runs the 3-frame blink action with some pauses in the middle. The sequence is:
(start loop)
1 – Pause for 2 seconds
2 – Blink
3 – Pause for 3 seconds
4 – Blink
5 – Pause for 0.2 seconds
6 – Blink
7 – Pause for 2 seconds
(end loop)
This gives us a semi-realistic blinking animation like this:
I’ve spent the last few weeks testing out various 2D iPhone game engines and frameworks such as GameSalad and Corona. But I’ve decided to dedicate my time to learning Cocos2d instead. GameSalad uses an intuitive GUI where you can drag and drop sprites and write behaviours to quickly develop games. Similarly, Corona lets you create games using the simple Lua language. But they both cost money to publish to the app store (however, I think GameSalad have just launched a new plan where they take a cut from your sales).
Cocos2d on the other hand is open source and has a pretty big community of developers so it’s relatively easy to get help by searching or posting questions on its dev forums. It is a pretty mature and flexible framework that comes with a bunch of templates and libraries including Box2D and Chipmunk physics engines. It’s a proven framework since there are hundreds of games in the app store that were developed using Cocos2d. Trainyard, for example, was made entirely with Cocos2d and you probably know it’s one of the most popular games in the app store at the moment.
It is, however, all in Objective-C and in my opinion a pretty steep learning curve if you don’t know the language. There are alternatives as mentioned before but if you’re planning to seriously build games as well as apps for iOS you probably should try and learn Objective-C now.
The Cocos2d documentation isn’t fantastic so I’ve had to learn it slowly by looking at tutorials and code samples. Objective-C is an alien world to me so it’s like learning 2 languages at once. But once you get your head around it, it’s actually a lot of fun. I’m going to try and post a few tutorials on my blog from time to time but if you decide to sit down and learn Objective-C and Cocos2d, you may want to start here: