Porting Cocos2D game to OSX using SpriteBuilder

So you finished and polished your game for iOS by using Cocos2D and SpriteBuilder? Wouldn’t it be nice to publish your game on the Mac AppStore too? These tools and frameworks make it really simple to accomplish this project successfully. However, there are some real pitfalls to watch out for.

Since there is an ever-growing community around SpriteBuilder, I think there will be soon a native solution to generate OS X targets right out of your SpriteBuilder project. Nonetheless, for now we have to do it by hand.

 

Note 1:

The following system configuration was used for this tutorial.

Cocos2D for iPhone 3.1
SpriteBuilder 1.2.1
XCode 6.0
OS X 10.9.4

Note 2:

You can find the complete project and all resources used for this tutorial at the OSXEnable github repository.

 

10 Easy steps to port Cocos2D to OSX

1. First of all add a new OS X target within XCode and use the Cocoa Application template. For this showcase, I will use MyGame and MyGameOSX as target names.

OSXEnabled1

 

2. Now we have to add the Cocos2D-OSX library to our new target. For that, simply drag an drop cocos2d-osx.xcodeproj  (can be found at Source/libs/cocos2d-iphone ) to your libs folder within XCode. Additionally, head over to MyGameOSX target settings and link the static library libcocos2d.a  (from the cocos2-osx project).

OSXEnabled2

 

3. Add additional frameworks like Foundation, AudioToolbox, OpenAl, AVFoundation, QuartzCore, AppKit, OpenGL, GameKit, libz.dylib.

 

4. Next, we need to set up some header search paths for Cocos2D. We do this at the Build Settings of the MyGameOSX target. Add following paths with type recursive:

"Source/libs/cocos2d-iphone/cocos2d"
"Source/libs/cocos2d-iphone/external/kazmath/include"
"Source/libs/cocos2d-iphone/external/ObjectAL"
"Source/libs/cocos2d-iphone/cocos2d-ui"

OSXEnabled4

 

5. Add Other Linker Flags -ObjC -lz  to your target Build Settings.

OSXEnabled8

 

6. Add resources and source code to your new OS X target. Here you simply need to check the Target Membership for your source files (e.g. game scenes, game logic, etc.) and your resources. Especially the resources generated by SpriteBuilder need to be added to your target.

OSXEnabled5

 

7. The next steps are dealing with the setup of your main window and view. Go to MainMenu.xib, click on the window object and add a OpenGL View as a new subview. Set the Custom Class of this view to CCGLView . Also, I did set the size of the window and view to 480×320 since we will use the resources optimized for a phone display.

OSXEnabled6

 

8. Set OpenGLView properties of your recently added view:

OSXEnabled7

 

9. Add an outlet named glView  to your app delegate.

 

10. Implement your app delegate which includes the basic steps for setting up the resources search paths and initializing the CCDirector .

#import "AppDelegate.h"
#import "CCBReader.h"

@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;

@end


@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Setup file utils and search paths
    [self setupFileUtils];

    // Setup and load your sprite frames
    [self setupSpriteFrames];

    // Setup Cocos2D and run first scene
    [self setupCocos2d];
}

- (void)applicationWillTerminate:(NSNotification *)aNotification
{
}


#pragma mark - Helper and setup methods

- (void) setupFileUtils
{
    // Configure CCFileUtils to work with SpriteBuilder
    CCFileUtils *sharedFileUtils = [CCFileUtils sharedFileUtils];
    
    sharedFileUtils.directoriesDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
                                       @"resources-phone", CCFileUtilsSuffixMac,
                                       @"resources-phonehd", CCFileUtilsSuffixMacHD,
                                       nil];
    
    sharedFileUtils.searchPath = [NSArray arrayWithObjects:
                                  [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Published-iOS"],
                                  [[NSBundle mainBundle] resourcePath],
                                  nil];
    
    sharedFileUtils.searchMode = CCFileUtilsSearchModeDirectory;
    [sharedFileUtils buildSearchResolutionsOrder];
    [sharedFileUtils loadFilenameLookupDictionaryFromFile:@"fileLookup.plist"];
}

- (void) setupSpriteFrames
{
    [[CCSpriteFrameCache sharedSpriteFrameCache] loadSpriteFrameLookupDictionaryFromFile:@"spriteFrameFileList.plist"];
}

- (void) setupCocos2d
{
    // Setup the CCDirector for Mac
    CCDirectorMac *director = (CCDirectorMac*) [CCDirector sharedDirector];
    [director setResizeMode:kCCDirectorResize_NoScale];
    [director setProjection:CCDirectorProjection2D];
    
#ifdef DEBUG
    // Enable FPS and SPF
    [director setDisplayStats:YES];
#endif
    
    // Connect the OpenGL view with the director
    [director setView:self.glView];
    [self.glView setFrameSize:NSMakeSize(self.window.frame.size.width,self.window.frame.size.height)];
	   
    // Enable "moving" mouse event. Default no.
    [self.window setAcceptsMouseMovedEvents:NO];
    [self.window center];
    [self.window setRestorable:NO];

    // Run the first scene
    [director runWithScene:[self startScene]];
}


- (CCScene*) startScene
{
    return [CCBReader loadAsScene:@"MainScene"];
}

@end

 

That’s it. Compile and run your project and you should see a nice landscape window with your first scene running.

OSXEnabled9

 

 

Further hints:

1. I had to update the XCode projects settings since the used version of SpriteBuilder did not use the latest project configurations. This was done automatically by XCode and worked very well.

2. If you want to use your tablet resources just update the size of your OpenGL view to e.g. 1024×768 and do some minor code changes within your app delegate:

    // Support for tablet resources
    sharedFileUtils.directoriesDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
                                       @"resources-tablet", CCFileUtilsSuffixMac,
                                       @"resources-tablethd", CCFileUtilsSuffixMacHD,
                                       nil];
    [sharedFileUtils setMacContentScaleFactor:2.0];
    // Update content scale for tablet support
    [director setContentScaleFactor:2.0];

3. The first time I tried to archive the project and build a submittable bundle, I got the following error: “APP” does not contain a single–bundle application or contains multiple products. Please select another archive, or adjust your scheme to create a single–bundle application. In this case you need to do some additional updates on your targets project settings. First go to the Build Phases of the corresponding Cocos2D OS X target and make sure that all Headers are within the Project section an nowhere else. In my case the header file NSEvent+CC.h  was placed at the Public section and I had to move it to the Project section.

OSXEnabled10

Next, go to the Build Settings of your Cocos2d OS X target and set the flag Skip Install to YES. This needs to be done for all external libraries if you use further ones. After that, archiving did succeed.

4. Do not forget to review and update your menu entries within MainMenu.xib  and remove all options you do not need (e.g. Save, Print, etc.). If there are still options which do not belong to your app it will be rejected within the app review.

 

Leave a Reply

Your email address will not be published. Required fields are marked *