Games
Cocos2d-x For Cross Platform Mobile Apps Development
December 22, 2011
0


Cocos2d has always been a popular choice for iPhone game development.  Now there’s now cocos2d-x (http://www.cocos2d-x.org/), a spinoff initiated by Walzer Wang. cocos2d-x is a cross platform version of cocos2d that produces iOS and Android app (plus Windows executable output as bonus if you like).  Cocos2d-x accomplishes the cross-platformness by using native C/C++ code.  This means that, yes, you need to use C/C++ for most of your code.

After trying it and running the examples, cocos2d-x seems to be a solid choice for cross platform development.

This walkthrough is my experience in getting the sample code to compile and run. I stumbled along the way and hopefully this guide can help you in some ways.

One of the first thing I tried was to compile the Sample game by Ray Wenderlich, for iOS and Android, which can be found at: http://www.cocos2d-x.org/attachments/535/Cocos2dxSimpleGame-0.9.1.rar (aka “The -x port of RayWenderlich‘s Cocos2dSimpleGame”).

The sample game is an arcade game where you shoot incoming aliens by touching the screen to set bullet directions.  I successfully ran it on an iPad 2, an iPod Touch, a Nook Color and a Kindle Fire.

As you examine the code, pay attention to are stub files that handle the platform specific tasks and you can even mix and match when you want.  On the Android, these are the Activity class and the JNI stubs, while in iOS, there are the ViewControllers and Delegates. Notice that these stub files does not contain much (which is good), and you can even use the same stub as a template.

Setting up the environment is half of the battle, especially getting the NDK (this is Android’s Native Code (C/C++) interface) on the Android side, while on iOS, it’s a lot more straightforward if you are already savvy with XCode.   On Android, I specifically used the Sequoyah plug-in.

On iOS.

Assuming you already have XCode installed (version 3 or 4), then using cocos2d-x in XCode is straightforward. I am using XCode 4.3.

  1. Extract the cocos2d-x example code (http://www.cocos2d-x.org/attachments/535/Cocos2dxSimpleGame-0.9.1.rar)
  2. Open the included xcodeproj file.
    Browse to this folder where you extracted the files: <your-folder>Cocos2dxSimpleGameCocos2dxSimpleGame.

 

  • Build the project in XCode….I got this error . This might have been fixed in the latest version, but the version that I downloaded are not finding some files (in red):
    And you might also received this error:

    cocos2d libraries Group
    Command /DeveloperXCode4.2/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 failed with exit code 1
    Command /DeveloperXCode4.2/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 failed with exit code 1
    Command /DeveloperXCode4.2/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 failed with exit code 1
    Command /DeveloperXCode4.2/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 failed with exit code 1
    

    If you look at &ltyour-folder>Cocos2dxSimpleGameCocos2dxSimpleGamelibss folder, you’ll see that it’s empty, so just copy the lib files from &ltyour-folder>Cocos2dxSimpleGamecocos2x and &ltyour-folder>Cocos2dxSimpleGameCocosDenshions into &ltyour-folder>Cocos2dxSimpleGameCocos2dxSimpleGamelibs. (Note: Might be possible to do folder symbolic link? I didn’t try that.)

  • Do another Build in XCode and this error might appear — this appears to depend of your XCode version:
    Unsupported compiler 'GCC 4.2' selected for architecture 'i386'
    

    I think this is because the project was built with XCode 3 and I am using 4. To fix it, go to the Build Settings and make sure these circled values are valid:

    In the Compiler for X/C++/Objective C section, if it says Unrecognized, chose either the Apple LLVM Compiler or LLVM Compiler.

    Do the same for the cocos2dx libraries target.

    If you get this error when running on Simulator 4.3:

    dyld: Library not loaded: /usr/lib/libc++abi.dylib
      Referenced from: /Users/Ferry/Library/Application Support/iPhone Simulator/4.3.2/Applications/F7A7BBFD-2749-46B3-B57B-B462CBFF4619/Cocos2dxSimpleGameForIOS.app/Cocos2dxSimpleGameForIOS
      Reason: image not found
    

    Goto here to see possible solutions:
    http://www.cocos2d-iphone.org/forum/topic/19384
    http://stackoverflow.com/questions/8178287/dyld-library-not-loaded-usr-lib-libcabi-dylib

  • Now Run it.I recommend that you also install the cocos2d-x XCode templates (&ltyour-cocos2d-x-folder>install-templates-xcode.sh) so you have these options when creating a new project:.
    sudo ./install-templates-xcode.sh
    

    More details on the official Wiki.

    On Android

    I run Mac OS and Windows but I primarily uses Windows to develop for Android so the guide below is for Windows Eclipse.   You need the Android NDK setup to compile cocos2d-x projects. Also, I am using the Sequoyah plug-in to enable NDK compilation from Eclipse. I don’t know about you, but I hate using command prompts and this plug-in makes creating native apps much more enjoyable.  The Sequoyah set-up is not straightforward but for me it’s worth it in the long run.  You can read about my set-up here: https://www.permadi.com/blog/2011/09/setting-up-android-jni-projects-in-windows-eclipse-and-sequoyah/.

    This guide assumes you have Sequoyah and Eclipse.

    Alternatively, you can read about running the environment without Sequoyah from the cocos2d-x wiki: http://www.cocos2d-x.org/projects/cocos2d-x/wiki

    1. Once the environment is set-up, open and extract the cocos2d-x example code (http://www.cocos2d-x.org/attachments/535/Cocos2dxSimpleGame-0.9.1.rar)
    2. Do File->New Project->Android Project->Create project from existing source..
    3. Browse to this folder where you extracted the files: &ltyour-folder>Cocos2dxSimpleGameCocos2dxSimpleGameandroid.

     

  • Within Eclipse, right click on the project, select Android Tools, then Add Native Support.  This step means that you can then automate the Build and Run steps within the Eclipse IDE.
  • Go and do Project Build.
  • The complication process can be slow the first time around. Pay attention to the Console (Window->Show View->Console) to see the progress. It may look something like this:
    
    **** Build of configuration Default for project Cocos2dxSimpleGame ****
    
    bash C:android-ndk-r5cndk-build V=1
    cygwin warning:
      MS-DOS style path detected: C:PERMADI_WORKSPACEAndroidExamplesCocos2dxSimpleGameCocos2dxSimpleGameandroid
      Preferred POSIX equivalent is: /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android
      CYGWIN environment variable option "nodosfilewarning" turns off this warning.
      Consult the user's guide for more details about POSIX paths:
        http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
    rm -f /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/lib*.so /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi-v7a/lib*.so /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/x86/lib*.so
    rm -f /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/gdbserver /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi-v7a/gdbserver /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/x86/gdbserver
    rm -f /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/gdb.setup /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi-v7a/gdb.setup /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/x86/gdb.setup
    Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
    mkdir -p /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi
    install -p /cygdrive/c/android-ndk-r5c/toolchains/arm-linux-androideabi-4.4.3/prebuilt/gdbserver /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/gdbserver
    Gdbsetup       : libs/armeabi/gdb.setup
    mkdir -p /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi
    echo "set solib-search-path C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/obj/local/armeabi" > /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/gdb.setup
    echo "directory C:/android-ndk-r5c/platforms/android-9/arch-arm/usr/include C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../cocos2dx/ C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../cocos2dx/include C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../cocos2dx/platform C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../cocos2dx/platform/third_party/android/iconv C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../cocos2dx/platform/third_party/android/libpng C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../cocos2dx/platform/third_party/android/libxml2 C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../cocos2dx/platform/third_party/android/libjpeg C:/android-ndk-r5c/sources/cxx-stl/stlport/stlport C:/android-ndk-r5c/sources/cxx-stl/system/include C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/../../../CocosDenshion/android/../include C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/helloworld/../../../../cocos2dx C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/helloworld/../../../../cocos2dx/platform C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/helloworld/../../../../cocos2dx/include C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/helloworld/../../../../CocosDenshion/include C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/jni/helloworld/../../../Classes" >> /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/gdb.setup
    Compile++ thumb  : cocos2d <= CCConfiguration.cpp
    /cygdrive/c/android-ndk-r5c/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-g++ -MMD -MP -MF C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/obj/local/armeabi/objs-debug/cocos2d/CCConfiguration.o.d.org -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__  -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -fno-rtti -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -
    
    ...............
    
    Compile++ thumb  : cocos2d <= CCLayer.cpp
    /cygdrive/c/android-ndk-r5c/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-g++ -MMD -MP -MF C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/obj/local/armeabi/objs-debug/cocos2d/layers_scenes_transitions_nodes/CCLayer.o.d.org -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__  -Wno-psabi -march=armv5te -mtune=xscale /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/obj/local/armeabi/libgame.so /cygdrive/c/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/libgame.so
    /cygdrive/c/android-ndk-r5c/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded C:/PERMADI_WORKSPACE/AndroidExamples/Cocos2dxSimpleGame/Cocos2dxSimpleGame/android/libs/armeabi/libgame.so
    
    **** Build Finished ****
    

    When the build is done, you’ll see the message **** Build Finished **** in the Console. Pay attention to the Console output because it is going to say **** Build Finished **** even if there’re errors. Errors are shaded in faint-red background in the Console. Another way to tell if there’s no error, when you try to run the app, it will refuse to run if there’s error.

  • You can run the game on the emulator or on a device. And that’s really all there is to it to compile. Sometimes Eclipse misbehaves and the compiler will complain about not finding GLES/gl.h.
    android/jni/../../../cocos2dx/platform/CCGL.h:58:21: error: GLES/gl.h: No such file or directory
    

    In this case, make sure that you set the target to >3 because GLES is 4 or later only:

    You might also encounter this kind of Eclipse FALSE WARNINGS galore (what fun!).

    Since Eclipse will refuse to let you Run the app, your option is to confirm that these are not real errors, and turn off the Syntax And Semantics Error warnings in the Eclipse (Preference->C/C++->General->Code Analysis).

    Do Clean and Build afterward.

    NOTES

    Shared Game Code

    Where are the game code?  Before answering that, note that there are two type of game code.  1) Shared 2) Platform specific.

    In the example code, the Shared code is located in /../../../Classes.  You can tell that they are Shared by the file type.  The Cpp files are Shared and the .java ones are for Android only.  You can see the list of the cpp files in jni/helloworld/

    LOCAL_SRC_FILES := main.cpp 
    ../../../Classes/AppDelegate.cpp 
    ../../../Classes/HelloWorldScene.cpp 
    ../../../Classes/GameOverScene.cpp
    

    In Eclipse, switch to Native Development perspective (you’ll have this Perspective if you did the Sequoyah install guide):

    Then expand the Project in the Project view:

    The Classes folder contains the game logic source files shared between platforms.

    The AppDelegate.cpp is the entry point common to all the platforms. It tells which Scene to run and you’ll find this line there:

        // create a scene. it's an autorelease object
        CCScene *pScene = HelloWorld::scene();
    

    The HelloWorld.cpp naturally contains the game itself. In this sample game, almost all the game logic is there.

    Specifying additional include paths:

    Android

    =====


    Open jni/Android.mk, add to this section:

    LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../../cocos2dx
    $(LOCAL_PATH)/../../../../cocos2dx/platform
    $(LOCAL_PATH)/../../../../cocos2dx/include
    $(LOCAL_PATH)/../../../../CocosDenshion/include
    $(LOCAL_PATH)/../../../Classes
    

    XCode

    ====

  • Goto Build Settings -> Header Search Paths

    Adding additional source files:

    For instance, there is a Box2D library in Cocos2d-x, you can use it by including it in the build:

    Android

    =====

    Examine the jni folder and open Application.mk:

    # it is needed for ndk-r5
    APP_STL := stlport_static
    APP_MODULES := cocos2d cocosdenshion game
    

    The APP_MODULES tells the compiler to compile.  In this case: cocos2d, cocosdenshion, and game module.  Where are those module defined?
    1. The game module is in jni/helloworld/Android.mk.
    2. The cocos2d-x module is defined at ../../../cocos2dx/Android.mk
    3. The cocosdenshion module is defined at ../../../CocosDenshion/Android.mk

    To add more library (such as the preincluded Box2D library)
    – open jni/Android.mk in this portion:

    subdirs := $(addprefix $(LOCAL_PATH)/../../../,$(addsuffix /Android.mk,
    cocos2dx
    CocosDenshion/android
    ))
    subdirs += $(LOCAL_PATH)/helloworld/Android.mk
    

    Android will look for Android.mk in each of those library folder (you can find premade Android.mk in each of those folder).

    – Then add the module name into Application.mk:

    APP_MODULES := cocos2d cocosdenshion game libbox2d
    

    Then find the main Activity file and add the library.

    static {
    System.loadLibrary("cocos2d");
    System.loadLibrary("cocosdenshion");
    System.loadLibrary("game");
    System.loadLibrary("libbox2d");
    }
    

    XCode

    ====

    Way more straightforward: just add them into the project and make sure any included files has their paths set in the Build Settings.