0
Porting and Maintaining Your
C++ Game
on Android
(without losing your mind)
Why C++


Cross-Platform support





(Some lesser platforms don’t have a JVM)

Don’t want to use Unity, etc
Existing ...
Overview




NDK recap
What goes where? C++ vs Java
Streamlining packaged app data






Eliminating Data Duplicati...
NDK

Application.mk

APP_PROJECT_PATH := $(call my-dir)
APP_BUILD_SCRIPT := $(call my-dir)/Android.mk
APP_MODULES
:= GHEng...
NDK

(static lib)

Android.mk

LOCAL_PATH := $(call my-dir)
LOCAL_CFLAGS := -Wno-psabi
LOCAL_CFLAGS += -D ANDROID
LOCAL_MO...
NDK

Android.mk
(shared lib – loaded by java)
LOCAL_MODULE := libGHEngine
LOCAL_SRC_FILES :=
../../GHEngine/obj/local/arme...
NDK
JNI
Loading the C++ Library
public class GHBowlingBaseActivity
extends Activity {
static {
System.loadLibrary("GHBowli...
NDK
JNI
Java (calling C++)
public class GHEngineInterface {
public native void runNativeFrame();
public native void launch...
NDK
JNI
C++ (called by Java)
static jobject globalEngineInterface = 0;
extern "C“ __attribute__((visibility("default")))
v...
NDK
JNI
Java (called by C++)
public class GHEngineInterface
{
public void showInterstitialAd() {
if (mInterstitialHandler ...
NDK
JNI
C++ (calling Java)


GHAndroidInterstitialAd class declaration:
JNIEnv& mJNIEnv;
jobject mEngineInterface;
jmetho...
What goes Where?
C++ or Java


C++





Java





All your platform-independent/pre-existing code
Bare minimum wrap...
What Goes Where
Java







OpenGL initialization
Sound through SoundPool
File handle loading through AssetManager
I...
What Goes Where
C++


All your game code




OpenGL rendering code





Ideally 90% of your app
Need to handle reini...
What Goes Where
Our code distribution.


2800 lines Java



1600 in base project
1200 in master project




Includes ...
Eliminating Data Duplication
Problem






Eclipse wants all data underneath
project
We want to reuse data (between
pro...
Eliminating Data Duplication
Solution



Batch file/shell script to copy data
On Mac

cp ../../../../../data/GHBowling/b...
Eliminating Data Duplication
Batch File Generation


Tool for initial generation


Looks through set of directories with...
Packaged App Data
Problem






Data is packaged through Android build
process
All files except those with certain
excl...
Excluded file extensions


Source: Android Asset Packaging Tool

/* these formats are already compressed, or don't
compre...
App Data Compression
Solution




One option: forgo Eclipse and pass –0
to the AAPT via command line
(universally or for...
Compiling for x86
(or other architectures)


In Application.mk:
APP_ABI := x86 armeabi


Supported values:






ar...
Compiling for x86
Problem


Shared library Android.mk needs to
include the correct static library for each
architecture
...
Compiling for x86
Solution
include $(CLEAR_VARS)
LOCAL_MODULE := libGHEngine
LOCAL_SRC_FILES :=
../../GHEngine/obj/local/$...
Building on Windows
Problem


We really like verbose filenames







GHBowlingYellowBallThrowWith190Degre
eSpinTrans...
Building on Windows
Problem


We really like verbose filenames







Ok, more like
GHGUIPopTransitionXMLLoader.cpp

...
Building on Windows
Solution







In Android.mk:
LOCAL_SHORT_COMMANDS := true
Build system generates intermediate li...
Porting and Maintaining your C++ Game on Android without losing your mind
Upcoming SlideShare
Loading in...5
×

Porting and Maintaining your C++ Game on Android without losing your mind

576

Published on

Presentation from David Wingrove & Katie Merrill from Golden Hammer Software http://www.goldenhammersoftware.com/

From the Barcelona Android User Group meetup: http://www.meetup.com/Barcelona-Android-User-Group/events/166734982/

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
576
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Porting and Maintaining your C++ Game on Android without losing your mind"

  1. 1. Porting and Maintaining Your C++ Game on Android (without losing your mind)
  2. 2. Why C++  Cross-Platform support    (Some lesser platforms don’t have a JVM) Don’t want to use Unity, etc Existing C++ Codebase
  3. 3. Overview    NDK recap What goes where? C++ vs Java Streamlining packaged app data     Eliminating Data Duplication Compiling multiple architectures Other quirks we’ve run into Some downloads info about our apps
  4. 4. NDK Application.mk APP_PROJECT_PATH := $(call my-dir) APP_BUILD_SCRIPT := $(call my-dir)/Android.mk APP_MODULES := GHEngine APP_OPTIM := release APP_STL := stlport_static APP_PLATFORM := android-8
  5. 5. NDK (static lib) Android.mk LOCAL_PATH := $(call my-dir) LOCAL_CFLAGS := -Wno-psabi LOCAL_CFLAGS += -D ANDROID LOCAL_MODULE := GHEngine LOCAL_MODULE_FILENAME := libGHEngine LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../../Base LOCAL_SRC_FILES += ../../../../Base/GHAppRunner.cpp include $(BUILD_STATIC_LIBRARY)
  6. 6. NDK Android.mk (shared lib – loaded by java) LOCAL_MODULE := libGHEngine LOCAL_SRC_FILES := ../../GHEngine/obj/local/armeabi/libGHEngine.a include $(PREBUILT_STATIC_LIBRARY) LOCAL_STATIC_LIBRARIES += libGHEngine include $(BUILD_SHARED_LIBRARY) $(shell cp libs/armeabi/libGHBowling.so ../../../GHBowlingBase/libs/armeabi)
  7. 7. NDK JNI Loading the C++ Library public class GHBowlingBaseActivity extends Activity { static { System.loadLibrary("GHBowling"); } }  Loads the file named libGHBowling.so
  8. 8. NDK JNI Java (calling C++) public class GHEngineInterface { public native void runNativeFrame(); public native void launchNativeApp(int windowWidth, int windowHeight, String externalStoragePath, int isTablet,int iapIsOn); //resizeWindow, handleTouchStart, handleTouchEnd, handleTouchPos //handleAcceleration, handleJavaPause, handleJavaResume, //handleJavaShutdown,handleBackPressed, calculatePublicKey, //onInterstitialRewardGranted,onRewardInterstitialAvailabilityChange, //onInterstitialDismiss, loadFile,handleTextureLoadConfirmed, //onAdActivation, onAdDeactivation, onIAPPurchase }
  9. 9. NDK JNI C++ (called by Java) static jobject globalEngineInterface = 0; extern "C“ __attribute__((visibility("default"))) void Java_goldenhammer_ghbowlingbase_GHEngineInterface_launchNativeApp (JNIEnv* env, jobject engineInterface, jint windowWidth, jint windowHeight, jstring jExternalStoragePath, jint isTablet, jint useIAP) { globalEngineInterface = env->NewGlobalRef(engineInterface); //Engine/Game Initialization goes here. }  When you shut down: env->DeleteGlobalRef(globalEngineInterface);
  10. 10. NDK JNI Java (called by C++) public class GHEngineInterface { public void showInterstitialAd() { if (mInterstitialHandler != null) { mInterstitialHandler.showInterstitial(); } else { onInterstitialDismiss(); } } };
  11. 11. NDK JNI C++ (calling Java)  GHAndroidInterstitialAd class declaration: JNIEnv& mJNIEnv; jobject mEngineInterface; jmethodID mShowAdMethod;  GHAndroidInterstitialAd ctor: jclass cls = mJNIEnv.GetObjectClass(mEngineInterface); mShowAdMethod = mJNIEnv.GetMethodID(cls, "showInterstitialAd", "()V");  GHAndroidInterstitialAd::activate: mJNIEnv.CallVoidMethod(mJavaObj, mShowAdMethod);
  12. 12. What goes Where? C++ or Java  C++    Java    All your platform-independent/pre-existing code Bare minimum wrapper for Android implementation of platform services Typical Android platform code Middleware integration  Can swap middleware vendors of the same service without touching C++ Exceptions:   OpenGL (initialization in Java, most code in C++ or GLSL) File I/O (mix of Java, C++)
  13. 13. What Goes Where Java       OpenGL initialization Sound through SoundPool File handle loading through AssetManager Image loading through BitmapFactory Google Play, In-App Billing, etc Ads and other middleware integration   AdMob, AdColony, Chartboost, PlayHaven, Facebook, etc Input Handling  (touches, accelerometer, buttons/gamepad)
  14. 14. What Goes Where C++  All your game code   OpenGL rendering code    Ideally 90% of your app Need to handle reinit after lost device fopen using file handle from Java Thin wrapper over JNI calls for everything else
  15. 15. What Goes Where Our code distribution.  2800 lines Java   1600 in base project 1200 in master project   Includes middleware integration 50k-150k lines C++   Varies depending on game 6400 Android-specific C++
  16. 16. Eliminating Data Duplication Problem    Eclipse wants all data underneath project We want to reuse data (between projects) in our own directory structure We hate maintaining multiple copies of the same data files.
  17. 17. Eliminating Data Duplication Solution   Batch file/shell script to copy data On Mac cp ../../../../../data/GHBowling/ballrollloop.wav ../../../GHBowling/assets/ballrollloop.wav cp ../../../../../data/Bowling/GHBowlingAndroid/backwall.jpg ../. ./../GHBowling/assets/backwall.jpg  On Windows copy ..........dataGHBowlingballrollloop.wav ......GHBowlingassetsballrollloop.wav copy ..........dataBowlingGHBowlingAndroidbackwall.jpg ... ...GHBowlingassetsbackwall.jpg
  18. 18. Eliminating Data Duplication Batch File Generation  Tool for initial generation  Looks through set of directories with a specified order of preference      Some files are different per-platform We may have Android-specific files We may not, but we prefer iOS-specific to generic Downside: some unnecessary files get copied Maintenance usually done by hand
  19. 19. Packaged App Data Problem    Data is packaged through Android build process All files except those with certain excluded file extensions (precompressed file types) are automatically compressed. Platform-agnostic file reading code doesn’t know to uncompress: sees garbage
  20. 20. Excluded file extensions  Source: Android Asset Packaging Tool /* these formats are already compressed, or don't compress well */ static const char* kNoCompressExt[] = { ".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg", ".aac", ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", ".amr", ".awb", ".wma", ".wmv" };
  21. 21. App Data Compression Solution   One option: forgo Eclipse and pass –0 to the AAPT via command line (universally or for certain extensions) What we do cp ../../../../../data/GHBowlingiOS/arrowpixel.glsl ../ ../../GHBowling/assets/arrowpixel.glsl.mp3
  22. 22. Compiling for x86 (or other architectures)  In Application.mk: APP_ABI := x86 armeabi  Supported values:      armeabi armeabi-v7a x86 mips all
  23. 23. Compiling for x86 Problem  Shared library Android.mk needs to include the correct static library for each architecture   For arm: /armeabi/libGHEngine.a For x86: /x86/libGHEngine.a
  24. 24. Compiling for x86 Solution include $(CLEAR_VARS) LOCAL_MODULE := libGHEngine LOCAL_SRC_FILES := ../../GHEngine/obj/local/$(TARGET_ARCH_ABI)/libGHEngine.a include $(PREBUILT_STATIC_LIBRARY)
  25. 25. Building on Windows Problem  We really like verbose filenames     GHBowlingYellowBallThrowWith190Degre eSpinTransitionXMLLoaderTransition.cpp Our GHEngine project has lots of files Linker includes all of those filenames in one shell command Exceeds maximum line length on Windows cmd (8191 characters)
  26. 26. Building on Windows Problem  We really like verbose filenames     Ok, more like GHGUIPopTransitionXMLLoader.cpp Our GHEngine project has lots of files Linker includes all of those filenames in one shell command Exceeds maximum line length on Windows cmd (8191 characters)
  27. 27. Building on Windows Solution     In Android.mk: LOCAL_SHORT_COMMANDS := true Build system generates intermediate list file and then invokes it with a much shorter command line Downside: slower compiles Can use only in projects that need it.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×