Cocos2d-x is a multiplatform game framework. It is a reimplementation of Cocos2D for iPhone in C++.
The main idea about it is that you are going to write plain old C++ code and that code will run on both Android (via JNI thanks to the NDK) and iPhone. It also has support for Win32, WoPhone and some other platforms, check them out on the Cocos2D-X website.
The zip that you can download from the project’s website includes wizards/helpers for creating a new project for each of the supported platforms, but it doesn’t have a wizard that will let you specify what platforms do you want to work on and then generate everything from one shot.
I took some time and figured out a way to manually create one of these hybrid projects for Android and iOS.
Before we begin
It is probably a better and considerably less painful option to just take the example HelloWorld project from the Cocos2D-x zip file and use that as a starting point for your project.
With a bit of care and finesse you should be able to rename the project files to match your game’s name.
Personally, I wanted to get a feel of the internal build process of a Cocos2D-x project, that’s why I decided I would hustle to see this through.
The first thing you need to do is set up your system paths. This is what my .bash_profile looks like:
export ANDROID_NDK_ROOT=~/Development/AndroidNDK/ export COCOS2DX_ROOT=~/Projects/Cocos2d-x/ export NDK_ROOT=~/Development/AndroidNDK/ export ANDROID_SDK_ROOT=~/Development/AndroidSDK/ export PATH=$PATH:$ANDROID_NDK_ROOT
Some parts of c2dx reference ANDROID_NDK_ROOT, some NDK_ROOT. Be as it may, we define both of them and add the path to the system path.
In order to create the hybrid project we will follow the steps below:
- create the iPhone project
- create the Android project
- merge the Android project into the iPhone project
I actively despise and hate XCode4 for a various number of reasons, and one of them is that when you create a new project it will place the project file in a folder above the one that contains the classes folder, that’s why I always keep around a copy of XCode3 (they appear to be happily cohabiting together).
Cocos2D-x provides a bunch of templates for both XCode3 and 4 that will create the project along with all that is needed. The templates for XCode3 are better suited for our goal, in the sense that they copy over the Cocos2D-X files for all the platforms supported by it, as opposed to the Xcode4 templates that will only copy the bare minimum.
To install the templates fire up a Terminal, navigate to the Cocos2D-x directory:
In order to install the templates you need to have root privilege, so we will call:
The terminal will then ask you what to install:
cocos2d-x template installer select the template version to install 3 for xcode3 4 for xcode4 input nothing for all
If you have both XCode3 and 4 installed, just hit enter, otherwise hit 3 for the XCode 3 templates.
Once you’ve done this, start up XCode and create a new project:
I called my new project SimpleGame so the next few examples will feature this name.
You should build and run your project now to make sure that it works properly.
A few considerations about the iPhone project
The main difference between creating an iPhone project first as opposed to an Android project is that the iPhone template will copy over and integrate the Cocos2D-x framework in the project’s structure, while Android will just keep a reference to it. Android projects by default are designed to be kept inside the cocos2dx folder.
A difference between the XCode3 and 4 templates is that XCode3 will store its resources in a folder called Resource (note the lack of the trailing s), while Xcode4 will use the standard Resources folder. This seems to be a typo in their system, but the good news is that the Android wizard uses the Resource folder as well. This will change in a future release as this “bug” appears to be fixed.
In the terminal get to the Cocos2D-x folder and type the following:
You will then be asked for a package path:
Input package path. For example: org.cocos2dx.example
Use something like
Then the wizard will ask you for the Android version that you want to support. Android 2.1 is a good choice:
Now cocos2d-x suppurts Android 2.1-update1, 2.2, 2.3 & 3.0 Other versions have not tested. Available Android targets: [...] id: 5 or "android-7" Name: Android 2.1-update1 Type: Platform API level: 7 Revision: 2 Skins: HVGA (default), QVGA, WQVGA400, WQVGA432, WVGA800, WVGA854 [...] id: 7 or "android-8" Name: Android 2.2 Type: Platform API level: 8 Revision: 2 Skins: HVGA (default), QVGA, WQVGA400, WQVGA432, WVGA800, WVGA854 [...] id: 9 or "android-9" Name: Android 2.3 Type: Platform API level: 9 Revision: 1 Skins: HVGA (default), QVGA, WQVGA400, WQVGA432, WVGA800, WVGA854 [...] input target id:
To select Android 2.1, type
5 and hit enter. You will then be asked for the project name:
input your project name:
Type SimpleGame and hit enter. A new folder will be created with this name in the Cocos2D-x directory and the project files will be copied inside.
Careful if you created the iPhone project and saved it in the Cocos2d-x folder – it may get overwritten. The best bet is to make sure that no other folders with the same name exist in here.
For some reason, the Android wizard will not set the appropriate executable flag on the
build_native.sh file so we are going to do that manually.
build_native.sh is the file that is used to compile the game for Android using the NDK. If you did not set the appropriate paths in your .bash_profile, build_native is going to crash on you because it won’t be able to find the
ndk-build executable from the NDK.
To make build_native.sh executable type the following in the terminal:
chmod u+x $COCOS2DX_ROOT/SimpleGame/android/build_native.sh
And to see if it really worked you can make a build:
If it all works out without any errors we are now ready to move to the last step.
When we will be done with this chapter, the structure of the game should be something like this:
First, we are going to create a makefile to help us test if the Android build script is still working properly.
That being said, fire up the editor of choice and create a file named makefile in the android subdirectory of the Cocos2d-x/SimpleGame folder:
clean: rm -rf libs/ rm -rf obj/
To exit and save, hit
Y, and then hit
Enter. From now on, calling
make clean in the Android directory will delete the already compiled binaries.
The actual merging will consist of copying over some of the folders from the Android directory, adjusting some values in the build_native.sh script and modifying a file from the iPhone project.
First, copy the android folder from
$COCOS2DX_ROOT/SimpleGame/android to the iPhone project directory, next to the
Then edit the
android/build_native.sh file and update the following paths:
# set params COCOS2DX_ROOT=../libs/cocos2dx GAME_ROOT=../ GAME_ANDROID_ROOT=$GAME_ROOT/android RESOURCE_ROOT=$GAME_ROOT/Resource
I deleted the
ANDROID_NDK_ROOT definition because that variable is already set by the
Next, open up the
android/jni/Android.mk file and make it look like the following:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) subdirs := $(addprefix $(LOCAL_PATH)/../../libs/,$(addsuffix /Android.mk, \ cocos2dx \ CocosDenshion/android \ )) subdirs += $(LOCAL_PATH)/helloworld/Android.mk include $(subdirs)
Next, open up the
android/jni/helloworld/Android.mk file and make it look like the following:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := game LOCAL_SRC_FILES := main.cpp \ ../../../Classes/AppDelegate.cpp \ ../../../Classes/HelloWorldScene.cpp LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../libs/cocos2dx \ $(LOCAL_PATH)/../../../libs/cocos2dx/platform \ $(LOCAL_PATH)/../../../libs/cocos2dx/include \ $(LOCAL_PATH)/../../../libs/CocosDenshion/include \ $(LOCAL_PATH)/../../../Classes # it is used for ndk-r4 # if you build with nkd-r4, uncomment it # LOCAL_LDLIBS := -L$(LOCAL_PATH)/../../libs/armeabi -lcocos2d -llog -lcocosdenshion \ # -L$(LOCAL_PATH)/../../libs/cocos2dx/platform/third_party/android/libraries -lcurl # it is used for ndk-r5 # if you build with ndk-r4, comment it # because the new Windows toolchain doesn't support Cygwin's drive # mapping (i.e /cygdrive/c/ instead of C:/) LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/armeabi) \ -lcocos2d -llog -lcocosdenshion \ -L$(call host-path, $(LOCAL_PATH)/../../../libs/cocos2dx/platform/third_party/android/libraries) -lcurl include $(BUILD_SHARED_LIBRARY)
What we have done is basically update the relative paths to match our folder structure — instead of going all the way to the folder above our project folder, we go to the root of our project and then enter the
The Xcode3 template has an issue that causes it to create the AppDelegate file (the entry file to your application) with the wrong filename, so instead of creating the files AppDelegate.h and AppDelegate.cpp, it will create SimpleGameAppDelegate.h and SimpleGameAppDelegate.cpp.
You will need to rename these two files in XCode to AppDelegate.h and .cpp, and change any old references to the SimpleGameAppDelegate.h file to the new file.
Since all seems to be done, go to the android folder and type in the terminal
make clean. This will delete all the previously compiled libs and objs so they can be rebuilt by the build script.
Now you should be able to call
build_native.sh from the android folder and have it successfully compile.
Each and every time you want to deploy an APK to an Android device (or virtual device) make sure you clean the project from inside Eclipse (Go to Project > Clean) and then right click the project and Run As > Android Application
Cleaning the project will force Eclipse to refresh the bundle files and take into account the newly compiled code when creating the game APK.
What is blatantly obvious from this entire article is that Cocos2D-x is seriously lacking in polishing with respect to developer tools.
You shouldn’t have to jump through that many hoops to be able to create a hybrid iPhone/Android multiplatform project. I haven’t even given thought to how to integrate this with the Win32 platform or anything similar, but I am guessing that’s another round of pain.
My bash-fu is seriously lacking, but it would be absolutely awesome and also a killer feature if one could create a script that would generate the necessary project architecture for the given architectures, something like:
~ ./create_project.sh Available platforms: ios - iOS (iPhone OS) android - Google Android win32 - Microsoft Windows wophone - WoPhone Please type the platforms that you want to support (e.g. ios android): > ios android win32 Project name (e.g. TestGame): > MyGame Project identifier (e.g. org.cocos2dx.testgame): > org.cocos2dx.mygame ======================= Available add-ons: chipmunk - Chipmunk physics engine box2d - Box2D physics engine lua - Support for the Lua scripting language none - None of the above Please type the add-ons that you want to add: > none ======================= == iOS ================ ======================= Do you want support for iPad? (yes/no) > no ======================= == Android ============ ======================= [... Android specific questions ...]
I’ll take a look what can be done with XCode’s CLI, maybe there is support for creating a new project from the command line.