Cocos2d-x is a multi-platform open source (MIT) C++ / OpenGL. With one source code, you can generate binaries for iPhone, Android, and more. That’s a big time saver.
Cocos2d-x is younger than its famous brother Cocos2d and despite being actively developed and quite stable already, it lacks of tutorials.
As I’ve struggled a bit to integrate Cocos2d-x into a UIKit application (UIVIewController), here is a walkthrough.
[UPDATE 2012-06-14] As pointed out in the comments, if you want to achieve the contrary (use UIKit components over a Cocos2d-x app), there is an open source project about it on GitHub shared by Di Wu.
[UPDATE 2012-06-28] New tutorial! Achieve the same thing on Android, launch a Cocos2d-x actvity in your Android apps.
http://www.youtube.com/v/J28NwrKLp50
0. Better than words, here is a sample project for people in a hurry. Sample project Cocos2dxOnUikit.zip.
1. You have a UIKit project on iPhone, at one time, you want to show a Cocos2d-x OpenGL view in a view controller.
2. Download the latest sources of Cocos2d-x (I used Cocos2d-x v1 / Opengl 1.1).
3. Unzip and have a look in cocos2dx/platform and cocos2dx/platform/third_party. There are many platforms you don’t need.
4. In Xcode (4.3 in my case), add all sources you need (of course only add the source for iOS platform in cocos2dx/platform/ios and cocos2dx/platform/third_party/ios).
5. Remove references to cocos2dx/platform/CCImage.cpp and CCThread.cpp.
6. In your “Library Search Paths” $(SRCROOT)/cocos2dx/platform/third_party/ios/libraries/ (for the curl library used by cocos2dx)
7. In your “Headers Search Paths” add $(SRCROOT)/cocos2dx and $(SDKROOT)/usr/include/libxml2 (for libxml framework)
8. In “Other C++ Flags” add -DCC_UNDER_IOS
9. Copy and add AppDelegate.cpp and AppDelegate.h from the HelloWorld example (shipped with the Cocos2d-x sources) into your project.
Comment out the applicationDidFinishLaunching() method as shown on the screenshot (this is more or less the code we will move into the ViewController later).
Side note : make sure the AppDelegate of your UIKit app is not called AppDelegate too as you would have in your project 2 AppDelegate.h files.
10. Change the extension of YourAppDelegate.m into YourAppDelegate.mm (for turning it into Objective C++ wich makes it compatible with C++ calls).
11. Add in YourAppDelegate.mm :
#import "AppDelegate.h"
static AppDelegate s_sharedApplication;
12. Now change the extension of YourViewController.m into YourViewController.mm.
13. Add this quick fix if it has not been merged in the main branch. To avoid a leak when releasing the OpenGL view.
14. In cocos2dx/support/zip_support/ioapi.cpp change fopen64 into fopen, fseeko64 into fseeko, ftello64 into ftello.
15. Add these frameworks.
OpenGLES.framework
libxml2.dylib
libz.1.2.5.dylib
QuartzCore.framework
16. Now, the last step, Cocos2d-x OpenGL view is integrated into the controller’s view (used as a modal view controller) :
-(void)loadOpenglScene:(CGRect)rect {
cocos2d::CCApplication::sharedApplication().run();
EAGLView *glView = [EAGLView viewWithFrame: rect
pixelFormat: kEAGLColorFormatRGBA8
depthFormat: GL_DEPTH_COMPONENT16_OES
preserveBackbuffer: NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
[self.view insertSubview:glView atIndex:0];
cocos2d::CCDirector *pDirector = cocos2d::CCDirector::sharedDirector();
pDirector->setOpenGLView(&cocos2d::CCEGLView::sharedOpenGLView());
// enable High Resource Mode(2x, such as iphone4) and maintains low resource on other devices.
// pDirector->enableRetinaDisplay(true);
// turn on display FPS
//pDirector->setDisplayFPS(true);
// pDirector->setDeviceOrientation(kCCDeviceOrientationLandscapeLeft);
// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60);
// create a scene. it's an autorelease object
cocos2d::CCScene *pScene_ = cocos2d::MyGraphicsEngine::scene(myparams);
// run
pDirector->runWithScene(pScene_);
// Retained because if not, we get an BAD ACCESS exception when we try to release the Cocos2d-x environment later
[[EAGLView sharedEGLView] retain];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// In this example we use a navigation bar and a "close" button, the Cocos2d-x view will be added below the navigation bar
UINavigationBar *bar=[[[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 49)] autorelease];
[self.view insertSubview:bar atIndex:0];
UIBarButtonItem *closeButton=[[[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStyleDone target:self action:@selector(close)] autorelease];
UINavigationItem *item = [[UINavigationItem alloc] initWithTitle:@""];
item.rightBarButtonItem = closeButton;
item.hidesBackButton = YES;
[bar pushNavigationItem:item animated:NO];
[item release];
[self loadOpenglScene:CGRectMake(0, bar.frame.size.height, self.view.frame.size.width, self.view.frame.size.height-bar.frame.size.height)];
}
-(void)close {
//TODO
}
-(void)viewDidDisappear:(BOOL)animated {
//Release Cocos2d-x stack
cocos2d::CCDirector *pDirector = cocos2d::CCDirector::sharedDirector();
//CCDirector::end() is asynchronous. That's why you can't release [EAGLView sharedEGLView] here after (you'll get a BAD ACCESS exception), and that's why we put it un viewDidUnload.
pDirector->end();
[self checkWin];
}
- (void)viewDidUnload {
[[EAGLView sharedEGLView] release];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
17. Stay tuned @jpsarda.