Your SlideShare is downloading. ×
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Porting and Maintaining your C++ Game on Android without losing your mind
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

501

Published on

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

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
501
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Porting and Maintaining Your C++ Game on Android (without losing your mind)
  • 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. 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. 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. 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. 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. NDK JNI Loading the C++ Library public class GHBowlingBaseActivity extends Activity { static { System.loadLibrary("GHBowling"); } }  Loads the file named libGHBowling.so
  • 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. 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. NDK JNI Java (called by C++) public class GHEngineInterface { public void showInterstitialAd() { if (mInterstitialHandler != null) { mInterstitialHandler.showInterstitial(); } else { onInterstitialDismiss(); } } };
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Compiling for x86 (or other architectures)  In Application.mk: APP_ABI := x86 armeabi  Supported values:      armeabi armeabi-v7a x86 mips all
  • 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. 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. 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. 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. 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.

×