Answer: PhysicsEditor
The PhysicsEditor is a shape editor for physics engines like Box2D and Chipmunk.
Before when I was making physics objects in Cocos2D, I used VertexHelper (Johannes Fahrenkrug), which is great and all, but there were a lot of things that you had to consider, such as you had to define the vertices yourself (meaning: ‘click “around” each sprite to define it’s vertices’) and you have to make sure that you don’t accidentally create any concave polygons (what are concave polygons again? check Wikipedia), and then you have to copy paste the generated code into your project. VertexHelper served me well and all, and it was free.
But PhysicsEditor did make me life a whole lot easier.
Andreas Loew wrote tutorials on his blog on how to use PhysicsEditor with Cocos2D:
So I used random.org to draw the winners… and the winners are… *drumroll*…
- tetna
- win_t
- mishta
- cocos2Developer
Since I allowed different ways to enter my contest, some of the winners on the list are from the cocos2d forums, while some are on Twitter.
So winners, please contact me (or check your forum messages or DMs) :)
“Cocos2d for iPhone 1 Game Development Cookbook” is written by Nathan Burba (@nathanburba).

UPDATE: This contest is now closed
Like I mentioned in my previous post, Packt published a new Cocos2d book and they asked me to hold a giveaway contest. I’m holding it both here and in the Cocos2d forums (http://www.cocos2d-iphone.org/forum/topic/28099).
So here it is, rules, rules:
- Just visit the Packt book page http://www.packtpub.com/cocos2d-for-iphone-1-game-development-cookbook/book and list one particular feature that makes you want to own the book, and list it as a comment EDIT: here (tumblr blog) or cocos2d forum thread (http://www.cocos2d-iphone.org/forum/topic/28099) or tweet me (@purplelilgirl) or email me (purplelittlegirl@yahoo.com)
- Also tweet the Packt book link: “New book on cocos2d game development: http://www.packtpub.com/cocos2d-for-iphone-1-game-development-cookbook/book”.
- I will select a winner using random.org :)
- Contest ends on 12 Noon Pacific Standard Time January 18th.
There, pretty simple right? :)
Also ManiacDev is also holding a book giveaway contest, he is giving away Unity3D and iOS books. If you guys are interested you can check out his blog: http://maniacdev.com/2012/01/giveaway-get-a-unity-3d-or-ios-book-there-will-be-6-winners-enter-here/
That’s about it :)
Packt recently released a new Cocos2d book: “Cocos2d for iPhone 1 Game Development Cookbook” by Nathan Burba.

Overview of Cocos2d for iPhone 1 Game Development Cookbook
- Discover advanced Cocos2d, OpenGL ES, and iOS techniques spanning all areas of the game development process
- Learn how to create top-down isometric games, side-scrolling platformers, and games with realistic lighting
- Full of fun and engaging recipes with modular libraries that can be plugged into your project
- Over 90 recipes for iOS 2D game development using cocos2d
Link: http://www.packtpub.com/cocos2d-for-iphone-1-game-development-cookbook/book
Okay, so I figured out how to add audio to my video.
In my previous blog post (http://purplelilgirl.tumblr.com/post/10974345146/mini-tutorial-how-to-capture-video-of-iphone-app-in), I managed to take a video of my app and save it into a file. However I am just stringing together screenshots of my app taken at every 0.1 second, so it doesn’t capture the audio.
So I have a different function that is capturing my audio (AVAudioRecorder), and saving that into a file.
Now, to combine the files together. Since iOS 4.1, AVFoundation included this thing called AVMutableComposition, and with that you can make composites of stuff, like combine video and audio files together to make a new video file that has audio.
So code bits (I found bits of the code in StackOverflow):
-(void) processVideo: (NSURL*) videoUrl
{
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL: videoUrl options:nil];
AVMutableComposition* mixComposition = [AVMutableComposition composition];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSError * error = nil;
for (NSMutableDictionary * audioInfo in appDelegate.audioInfoArray)
{
NSString *pathString = [[NSHomeDirectory() stringByAppendingString:@”/Documents/”] stringByAppendingString: [audioInfo objectForKey: @”fileName”]];
AVURLAsset * urlAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:pathString] options:nil];
AVAssetTrack * audioAssetTrack = [[urlAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID: kCMPersistentTrackID_Invalid];
NSLog(@”%lf”, [[audioInfo objectForKey: @”startTime”] doubleValue]);
CMTime audioStartTime = CMTimeMake(([[audioInfo objectForKey: @”startTime”] doubleValue]*TIME_SCALE), TIME_SCALE);
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,urlAsset.duration) ofTrack:audioAssetTrack atTime:audioStartTime error:&error];
}
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
atTime:kCMTimeZero error:nil];
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetPassthrough];
NSString* videoName = @”export.mov”;
NSString *exportPath = [[self pathToDocumentsDirectory] stringByAppendingPathComponent:videoName];
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
{
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}
_assetExport.outputFileType = @”com.apple.quicktime-movie”;
NSLog(@”file type %@”,_assetExport.outputFileType);
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;
[_assetExport exportAsynchronouslyWithCompletionHandler:
^(void ) {
switch (_assetExport.status)
{
case AVAssetExportSessionStatusCompleted:
//export complete
NSLog(@”Export Complete”);
//[self uploadToYouTube];
break;
case AVAssetExportSessionStatusFailed:
NSLog(@”Export Failed”);
NSLog(@”ExportSessionError: %@”, [_assetExport.error localizedDescription]);
//export error (see exportSession.error)
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@”Export Failed”);
NSLog(@”ExportSessionError: %@”, [_assetExport.error localizedDescription]);
//export cancelled
break;
}
}];
}
I have more than one audio file that I want to combine with my video, so I created a array file that contains information for each of the audio files (such as where the file is located and when to play that audio).
And that’s it :) You have a video of your app :) with audio :)
Someone asked me before if I knew how to do record the screen in Cocos2d as a video. I didn’t know how to record a video, so this guy sent me some codes, but his problem is that his code is recording the screen (taking screenshots) as a UIWindow. So my idea for him was to replace his screenshot code with AWScreenshot (by Manucorporat, search the Cocos2d forums for his code).
And here are the code bits:
#import <AVFoundation/AVFoundation.h>
#import <AVFoundation/AVAssetWriter.h>
#import <CoreVideo/CVPixelBuffer.h>
#import <CoreMedia/CMTime.h>
#import “AWScreenshot.h”#define FRAME_WIDTH 320
#define FRAME_HEIGHT 480
#define TIME_SCALE 60 // frames per second-(void) startScreenRecording
{
NSLog(@”start screen recording”);
// create the AVAssetWriter
NSString *moviePath = [[self pathToDocumentsDirectory] stringByAppendingPathComponent: @”video.mov”];
if ([[NSFileManager defaultManager] fileExistsAtPath:moviePath])
{ [[NSFileManager defaultManager] removeItemAtPath:moviePath error:nil];
}
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
NSError *movieError = nil;
[assetWriter release];
assetWriter = [[AVAssetWriter alloc] initWithURL:movieURL
fileType: AVFileTypeQuickTimeMovie
error: &movieError];
NSDictionary *assetWriterInputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:FRAME_WIDTH], AVVideoWidthKey,
[NSNumber numberWithInt:FRAME_HEIGHT], AVVideoHeightKey,
nil];
assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo
outputSettings:assetWriterInputSettings];
assetWriterInput.expectsMediaDataInRealTime = YES;
[assetWriter addInput:assetWriterInput];
[assetWriterPixelBufferAdaptor release];
assetWriterPixelBufferAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc]
initWithAssetWriterInput:assetWriterInput
sourcePixelBufferAttributes:nil];
[assetWriter startWriting];
firstFrameWallClockTime = CFAbsoluteTimeGetCurrent();
[assetWriter startSessionAtSourceTime: CMTimeMake(0, TIME_SCALE)];
// start writing samples to it
[assetWriterTimer release];
assetWriterTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector (writeSample:)
userInfo:nil
repeats:YES] ;
}-(void) stopScreenRecording
{ [assetWriterTimer invalidate];
assetWriterTimer = nil;
[assetWriter finishWriting];
NSLog (@”finished writing”);
}
As you can see startScreenRecording is calls writeSample.
-(void) writeSample: (NSTimer*) _timer
{ if (assetWriterInput.readyForMoreMediaData)
{
CVReturn cvErr = kCVReturnSuccess;
// get screenshot image!
CGImageRef image = (CGImageRef) [[self createARGBImageFromRGBAImage:[self screenshot]] CGImage];
// prepare the pixel buffer
CVPixelBufferRef pixelBuffer = NULL;
CFDataRef imageData= CGDataProviderCopyData(CGImageGetDataProvider(image));
cvErr = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
FRAME_WIDTH,
FRAME_HEIGHT,
kCVPixelFormatType_32ARGB,
(void*)CFDataGetBytePtr(imageData),
CGImageGetBytesPerRow(image),
NULL,
NULL,
NULL,
&pixelBuffer);
// calculate the time
CFAbsoluteTime thisFrameWallClockTime = CFAbsoluteTimeGetCurrent();
CFTimeInterval elapsedTime = thisFrameWallClockTime - firstFrameWallClockTime;
//NSLog (@”elapsedTime: %f”, elapsedTime);
CMTime presentationTime = CMTimeMake (elapsedTime * TIME_SCALE, TIME_SCALE);
// write the sample
BOOL appended = [assetWriterPixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentationTime];
if (appended)
{ NSLog (@”appended sample at time %lf”, CMTimeGetSeconds(presentationTime));
} else
{ NSLog (@”failed to append”);
[self stopScreenRecording];
}
}
}
And the code I used to take screenshot:
- (UIImage*)screenshot
{ return [AWScreenshot takeAsImage];
}
Notice how I called [[self createARGBImageFromRGBAImage: [self screenshot]], it’s because my UIImage is a RGBAImage, while the CVPixelBuffer’s format type is kCVPixelFormatType_32ARGB, so I had to fix thing so they match or else, my video would come up in weird tints.
I found the Googled for the createARGBImageFromRGBAImage code, and here it is:
-(UIImage *) createARGBImageFromRGBAImage: (UIImage*)image
{ CGSize dimensions = [image size];
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * dimensions.width;
NSUInteger bitsPerComponent = 8;
unsigned char *rgba = malloc(bytesPerPixel * dimensions.width * dimensions.height);
unsigned char *argb = malloc(bytesPerPixel * dimensions.width * dimensions.height);
CGColorSpaceRef colorSpace = NULL;
CGContextRef context = NULL;
colorSpace = CGColorSpaceCreateDeviceRGB();
context = CGBitmapContextCreate(rgba, dimensions.width, dimensions.height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault); // kCGBitmapByteOrder32Big
CGContextDrawImage(context, CGRectMake(0, 0, dimensions.width, dimensions.height), [image CGImage]);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
for (int x = 0; x < dimensions.width; x++) {
for (int y = 0; y < dimensions.height; y++) {
NSUInteger offset = ((dimensions.width * y) + x) * bytesPerPixel;
argb[offset + 0] = rgba[offset + 3];
argb[offset + 1] = rgba[offset + 0];
argb[offset + 2] = rgba[offset + 1];
argb[offset + 3] = rgba[offset + 2];
}
}
colorSpace = CGColorSpaceCreateDeviceRGB();
context = CGBitmapContextCreate(argb, dimensions.width, dimensions.height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrderDefault); // kCGBitmapByteOrder32Big
CGImageRef imageRef = CGBitmapContextCreateImage(context);
image = [UIImage imageWithCGImage: imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(rgba);
free(argb);
return image;
}
And there we go, I managed to record the screen of my Cocos2d app and then save it as a video file.
My next problem is, how do I add audio to my video?
Posting screenshots on Facebook and Twitter is a great way to show high scores and make your game known to the world. The problem is that writing code for authentication and poking around the different APIs is time consuming. Here is where Sharekit comes in handy. It is an open source library…
So you want to add Facebook integration to your iOS Cocos2d game (allow players to upload screenshots, videos or post stuff to their wall, like how awesome your game is). First off, hop to the Facebook Developers website and check out the Mobile part, there should be a Getting Started page, this page:
Getting Started Mobile Apps
https://developers.facebook.com/docs/guides/mobile/
Follow the steps. Once you’re done with that, you pretty much already know how to post the the player’s Facebook wall.
Next question, how to upload a photo or a video. For videos, just check out a how-to blog post by Christine Abernathy. Link:
How-To: Use the Graph API to Upload a Video (iOS)
https://developers.facebook.com/blog/post/532/
Just follow that tutorial.
For photos, just replace the video code to:
UIImage *img = [UIImage imageWithContentsOfFile: @”img.jpg”];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys: img, @”picture”, nil];
[delegate.facebook requestWithGraphPath:@”me/photos”
andParams:params
andHttpMethod:@”POST”
andDelegate:self];
But, but, but the samples are not for a Cocos2d project.
For a Cocos2d project it’s more or less the same.
So your AppDelegate.h will look something like this:
#import <UIKit/UIKit.h>
#import “FBConnect.h”
@interface AppDelegate : NSObject <UIApplicationDelegate, FBSessionDelegate, FBRequestDelegate>
{ UIWindow *window;
Facebook *facebook;
}
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) Facebook *facebook;
@property (nonatomic, retain) NSString *appId;
@end
Just take note of the Facebook related stuff. I also added a NSString appId, which will store our app’s id.
Somewhere in AppDelegate.m applicationDidFinishLaunching (before you run your game scene):
facebook = [[Facebook alloc] initWithAppId: @”<APPID>”];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@”FBAccessTokenKey”]
&& [defaults objectForKey:@”FBExpirationDateKey”])
{ facebook.accessToken = [defaults objectForKey:@”FBAccessTokenKey”];
facebook.expirationDate = [defaults objectForKey:@”FBExpirationDateKey”];
}
And then as mentioned in the previous examples, add this to code as well:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{ return [facebook handleOpenURL:url];
}
When I ran my app on my device I encountered this error:
sgx error: background gpu access not permitted
So I Googled and found this link:
http://dougdiego.com/2010/10/01/sgx-error-background-gpu-access-not-permitted/
And it said add these lines of codes to the AppDelegate code:
- (void)applicationDidEnterBackground:(UIApplication *)application
{ [[CCDirector sharedDirector] stopAnimation];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{ [[CCDirector sharedDirector] startAnimation];
}
- (void)applicationWillResignActive:(UIApplication *)application
{ [[CCDirector sharedDirector] pause];
}- (void)applicationDidBecomeActive:(UIApplication *)application
{ [[CCDirector sharedDirector] resume];
}
Now in your game scene, or wherever in your game that needs some Facebook thingamajigie, like when the player clicks on an upload screenshot to Facebook button: (These codes are based on the upload video tutorial)
-(void) uploadToFacebookTapped: (id) sender
{ AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
if (![delegate.facebook isSessionValid])
{
NSArray* permissions = [[NSArray arrayWithObjects:
@”publish_stream”, @”user_photos”, nil] retain];
[delegate.facebook authorize:permissions delegate: self];
} else
{ [self uploadScreenshot];
}}
- (void)fbDidLogin
{ [self uploadScreenshot];
}
-(void)fbDidNotLogin:(BOOL)cancelled
{ NSLog(@”fbDidNotLogin”);
}-(void) uploadScreenshot
{ AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent: @”screenshot.png”];
UIImage *img = [UIImage imageWithContentsOfFile: path];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
img, @”picture”,
nil];
[delegate.facebook requestWithGraphPath:@”me/photos”
andParams:params
andHttpMethod:@”POST”
andDelegate:self];
}
So what happens is, if your player is not logged into Facebook and is using the Facebook function for your app for the first time (for that session), it will redirect the player to the Facebook app, or a web browser to allow the player to login and authorize your app. Once that is done, the fbLogin function will be called. And then uploadScreenshot.
And the call back code:
- (void)request:(FBRequest *)request didLoad:(id)result
{ if ([result isKindOfClass:[NSArray class]])
{ result = [result objectAtIndex:0];
}
NSLog(@”Result of API call: %@”, result);
}
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error
{ NSLog(@”Failed with error: %@”, [error localizedDescription]);
}
After the screenshot has been upload, request didLoad will be called, if there is some kind of error along the way, request didFailWithError will be called.
And that’s it :)
Written by Rod Strougo and Ray Wenderlich
Tiny Wings is this adorable game by Andreas Illiger that involves this tiny bird who dream of flying.
It is extremely popular on the App store, and that is probably why lots of people wants to know how to make a game like it.
These are some links to tutorials and remake projects.
Sergey Tiknohov (@haqu) is working on a Tiny Wings remake project.
Ray Wenderlich wrote a tutorial based on Sergey’s project, which is divided into 2 parts. The tutorial uses Cocos2d and Box2d.
- http://www.raywenderlich.com/3857/how-to-create-dynamic-textures-with-ccrendertexture
- http://www.raywenderlich.com/3888/how-to-create-a-game-like-tiny-wings-part-1
- http://www.raywenderlich.com/3913/how-to-create-a-game-like-tiny-wings-part-2
@jpsarda wrote a blog post on how to make the gorgeous hills in Tiny Wings using Cocos2d.
Emanuele Feronato wrote a tutorial on how to make the Tiny Wings terrain using Flash and Box2d.
- http://www.emanueleferonato.com/2011/07/14/create-a-terrain-like-the-one-in-tiny-wings-with-flash-and-box2d/


