Friday, May 24, 2013

Cocos2d-x for iOS and Android with IntelliJ

Cocos2d-x is a C++ port of the Cocos2d library and it allows you to write cross-platform games that work on both iOS and Android (and a couple of other platforms as well).

Setting up a cross-platform project is a bit of work though. The C++ code you use for writing your games is the same for all platforms but you will need some platform-specific wrapper code and build-configuration to get things going on the different platforms you want to support.

Jean-Yves Mengant has written an in-depth guide on how to do just that and it offers everything you need to know to get going. That article focuses on getting the Android-specific code running in Eclipse. This makes sense, as Eclipse is the default IDE that even ships with the ADT Bundle Google offers. And even if you like another IDE better, you can ask yourself if it is even worth the trouble because the actual game will be written in C++, which can be done easier in Xcode anyhow (or AppCode :o).

IntelliJ has supported Android development for quite some time now, even in their free Community Edition. And Google has recently announced Android Studio, which is also based on IntelliJ. So I figured I'd give it a try and get a cross-platform project up-and-running using IntelliJ for the Android side of things.

Before we get started, I expect you to have installed IntelliJ, Xcode, Cocos2d-x, the Android SDK and the Android NDK so you are able to create and run both a Cocos2d-x iOS app in Xcode using the 'New Project'-wizard and a plain Android application in IntelliJ. In the next steps I'll show you how to setup a project that can be started from within Xcode (for iOS) and IntelliJ (for Android), using the same code base.

In Cocos2d-x we'll usually work iOS-first and then move on to other platforms. So let's first open Xcode and start a new project. Pick the 'cocos2dx' project template and click 'Next':

Now enter a Product Name and a Company Identifier for your project and click 'Next':

Then select your project folder to save your project in and click 'Create'. Xcode wil create the project for you and you're ready to go. You can immediately click 'Run' and the default Cocos2d-x 'Hello World'-application will fire up on whatever device or simulator you have configured as default in Xcode:

OK, time to move on to Android. Locate the folder where you extracted the Cocos2d-x framework. It should hold a file named ''. Open this file in your favorite text-editor and change the parameters NDK_ROOT_LOCAL and ANDROID_SDK_ROOT_LOCAL and point them to the location you installed the Android NDK and the Android SDK on your system. Make sure you save the file.

Now open a console and step into the directory that holds the Cocos2d-x framework. Execute the script you just updated (./ You will be asked to provide a package for your application. Type in the package you'd like to use for your Android project and continue.

Now you'll get a list of available Android versions and you are asked to provide the input target id. I usually set this to the id matching "Google Inc.:Google APIs:14", which is Android API Level 14 and some additional Google libraries for USB and Google Maps. For me that translates to id 2:

And finally you are asked for a project name. I'm using 'Pong' here:

Your Android project will now be created for you and once the script is done, you'll see that there is a new folder inside the Cocos2d-x framework folder with the name of your project (in my case 'Pong'). If you take a look inside that folder, you'll find another folder named This is the folder we are most interested in. Select the folder in Finder and copy it.

Now use Finder to browse to the iOS project you created using Xcode. In your project folder, Xcode should have created a new folder structure. If you also named your project 'Pong', you'll see a 'Pong' directory that holds another 'Pong' directory. Paste the folder you copied earlier into the innermost 'Pong' directory. You can now remove the Android 'Pong' folder inside the Cocos2d-x framework folder that we generated using the script.

While you're in the Cocos2d-x framework folder, select the folders 'cocos2dx', 'CocosDenshion' and 'extensions' and copy them. Again locate the Xcode iOS project folder using Finder and step into Pong/Pong/libs. Paste the folders you just copied into here. They should already be there but we need to make sure they are complete. So if asked to overwrite the existing file, do so.

Open the file /Pong/Pong/ in your favorite text editor. Directly after the first line that defines the APPNAME, set the NDK_ROOT:

Then locate these lines:
# ... use paths relative to current directory

make sure you set the COCOS2DX_ROOT to the project libs folder:

Make sure you save the file. Using your console you can step into the Android project directory (Pong/Pong/ and execute the script:

This will build the C++ code in the project. It'll take some time to complete on the first run.

Ok, great! We have just created an iOS project as well as an Android project and merged the projects into a single folder that shares the C++ code. We also built the native code for our Android version. Now let's move on to IntelliJ.

Open IntelliJ and create a new project. Set the project name and point to the existing 'Pong/Pong/' folder. Make sure you pick your Android SDK as the project SDK and click 'Next'.

IntelliJ will continue to the next panel of the 'New Project' wizard that lets you select additional technologies for your project. We don't need any other technologies, so we can click 'Finish' now to create the project.

As soon as the project opens, IntelliJ will usually detect you're using Android in your project and prompt you to configure the framework. Otherwise you can manually add the Android facet to your module (File -> Project Structure... -> Facets -> '+' -> 'Android').

Using IntelliJ now, you can open the AndroidManifest.xml file. Make sure you set the minSdkVersion to 14.

Next, look for the line:
 <application android:label="@string/app_name"

Make sure the name of the icon matches the actual icon name in the 'res' folder. Most likely this is wrong and should be update to look something like this:

    <application android:label="@string/app_name"

After updating the AndroidManifest.xml file, you'll need to tell IntelliJ where to find the Cocos2d-x JNI Java files, which are required for the Java wrapper-code of your Android project. You can do this by opening 'File' -> 'Project Structure...' from the menu. Now select 'Modules', '' and make sure the 'Sources' tab is selected.

Now click 'Add Content Root' and select [Cocos2d-x root folder]/cocos2dx/platform/android/java/src and click 'OK' to confirm.

If you let IntelliJ configure Android for you when it detected it, you should already have a run-configuration added. Otherwise you'll have to add it manually. From the menu select 'Run' -> 'Edit Configurations...'. Then click the '+'-button and select 'Android Application'. Name your configuration (Pong) and select the module. You can also select your preferred Android Virtual Device here and then click 'OK':

You should now be able to use this Run-configuration to fire up the Cocos2d-x 'Hello World' application on your Android simulator:

Great. Now go back to IntelliJ and edit the Run Configuration you used to start the Android application. On the 'Before launch' panel click the '+'-button and select 'Run External tool'.
Here you can provide a name (Pong Native Build) a group (Android Native Builds) and a description (Builds the native code for Pong). Then you should select the script in your folder and make sure the Working directory is also set to your folder. Once you're done, click 'OK'.

You'll see you have created a new external tool and a group to hold it. Make sure 'Pong Native Build' is selected and click 'OK'.

Now select the newly created external tool in the 'Before launch' panel and click the up-arrow to move it to the top so it will be executed before 'Make'. If you are done, click 'OK' to confirm.

Now, let's make a small change in the C++ code. I'm going to use Xcode for this. Open the file HelloWorldScene.cpp and locate this line:

pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );

This line places the close-button in the 'Hello World'-app at the bottom right corner. Let's put it into the top left corner instead by changing the line into:

pCloseItem->setPosition( ccp(20, CCDirector::sharedDirector()->getWinSize().height - 20) );

Run the application in Xcode so you can verify the button is now indeed in the top left corner in the iPhone simulator or whatever iOS simulator or device you are using:

Return to IntelliJ. If you click run, the updated C++ code should automatically compile for your Android project and the app with the updated button-position should show up inside the Android Virtual Device:

I'll leave the implementation of the actual cross-platform 'Pong'-game up to you.