More Related Content
Similar to 0621 ndk game (20)
0621 ndk game
- 2. 自己紹介
• @cat_kaotaro こと はしづめかおり と申します
• 2009年の秋くらいからAndroidのおっかけしています
• 「Okusama」というアプリつくってます
• 会社ではAndroid技術者養成のための研修講師やお助け
マンやってます
• ACE(Androidアプリケーション技術者認定試験)の対策本
の執筆
– ベーシック対策実践問題集 (日経BP)2010年11月発売
– 徹底攻略ACE問題集(インプレスジャパン)2011年6月発売予定
- 4. 冒頭でJavaの駄目だし
• ほとんどの人がJava以外の言語がすきなんじゃないか
• Javaはすべてにおいて万能ではない
• ゲームはハイパフォーマンスが求められる
• C/C++の開発はNDKでやろう
– 既存のネイティブライブラリの再利用
– サブルーチンの高速化
– VFP (Vector Floating Point 浮動小数点演算機能)、NEONアクセス
– かといって絶対速くなるわけではないんだからね
• NDK?
– ツールチェイン(標準的なgccのクロスコンパイラ)
– Android 用のプラットフォームビルドシステム
– ヘッダとライブラリ(C,C++のランタイムなど)
• Stable ABI(Application Binary interface) - armeabi
– 移植したいライブラリがAndroidプラットフォームが持つシステムライブラ
リでは使用できないかも
- 6. NDKのセットアップ・開発手順
• 現在-r5b
• Android DevelopersとかNDK内のドキュメン
トに詳しく書いてある
• Application.mkに
APP_STL:=gnustl_static
を指定するとC++例外処理ができる
* gnustl_static -> Use GNU libstdc++ as a static library.
- 7. JNIのお作法1
• JNIのインタフェース実装(Java側)
– native 修飾子を使ってインタフェース名を定義
– javahコマンドかeclipseからJNIのヘッダファイルが作成
できる
• JNI接続部分(ネイティブ側)
– ファンクションテーブルを使ってJNIメソッドを管理
– シグネチャはjavapコマンドでわかるよ
– JNIメソッドをシステムに登録する
static JNINativeMethod gMethods[] = { JNIEnv* env;
{“init”, “(II)V”, (void*)nativeGameInit}. env -> FindClass
{“step”, “()V”, (void*)nativeStep} env ->RegisterNatives(jclass, ファンクション
}; テーブル,登録するメソッドの個数)
- 8. JNIのお作法2
• JNI接続部分(ネイティブ側)続き
– ネイティブ→Javaのコールバックのやり方
env->GetObjectClass // クラスの取得
env->GetMethodId // JavaメソッドのメソッドIDを取得
env->CallVoidMethod // 呼び出し
- 9. NDK ビルド/デプロイ/デバッグ
• ビルド・デプロイ
>[bash]ndk-build [NDK_DEBUG=1]
//Cのライブラリのビルド(.so)
>ant debug(or ant release) //Javaのビルド(class,apk)
>ant install
• デバッグ gdb
>[bash]ndk-gdb
端末とHostマシン間はgdb-rsp(RSP(リモートシリアルプロトコル )
HostマシンのgdbとEclipse/VSはgdb-MI((Machine Interface) )
Gingerbreadでgdbデバッグのいろんなところが改善されて
快適になったからみんなドシドシつかってね!!
メインスレッド以外のスレッドでもブレイクポイントが張れたりデバッグ機能
が強化したよ
- 11. – res/values-v9/bools.xml //動作するプラットフォームがGingerbreadの場合
<resources>
<bool name=“atLeastGingerbread”>true</bool>
<bool name=“notGingerbread”>false</bool>
</resources>
– res/values/bools.xml //動作するプラットフォームがGingerbreadでない場合
<resources>
<bool name=“atLeastGingerbread”>false</bool>
<bool name=“notGingerbread”>true</bool>
</resources>
– AndroidManifest.xml
<activity android:name=“.SANativeActivity”
android:enabled=“@bool/atLeastGingerbread”> <!--動作するプラットフォームがGingerbreadの場合-->
<meta-data android:name=“android.app.lib_name”
android:value=“sanative”>
<intent-filter>
<action android:name=“android.intent.action.MAIN”/>
<action android:category=“android.intent.category.LAUNCHER”/>
</intent-filter>
</activity>
<activity android:name=“.DemoActivity” <!--動作するプラットフォームがGingerbreadでない場合-->
android:enabled=“@bool/notGingerbread”>
<intent-filter>
<action android:name=“android.intent.action.MAIN”/>
<action android:category=“android.intent.category.LAUNCHER”/>
</intent-filter>
</activity>
- 12. プロジェクトのファイル構成(jniディレクトリ以下)
/jni/libsajni/ ←Gingerbread以外の時にロードするスタブライブラリ
∟Android.mk
∟app-android.c
/jni/libsanangels/ ←ゲームのエンジンの本体を格納(シェアする)
/jni/libsanative/ ←NativeActivityのメタデータのライブラリに指定
∟ Android.mk
∟ app-android-native.c
∟ glutils.c
∟ glutils.h
:
/src/com/example/sanangeles/DemoActivity.java ←通常のActivityをextends
System.loadLibrary(“sanangeles”)
System.loadLibrary(“sajni”)
/src/com/example/sanangeles/SANativeActivity.java ←NativeActivityをextends
System.loadLibrary(“sanangeles”)
- 13. ゲームアプリを作るうえで大切なこと
• Lifecycle
– backキーが押されたときやfinish()でクローズされるまでアプリのプロセスは
維持せよ
• 特にフォアグランドのアクティビティのプロセスは超重要
• killする(される)のは最後の手段
– visibleなアクティビティは高優先度で。
• バックグランドのアクティビティはさほど重要でない。アクティブでないアクティビ
ティを持つプロセスが最初にkillされるように
– アプリのイニシャライズ処理などをstatic関数にしたときは気をつけて
• プロセスがアクティブである間ライブラリはunloadされずにいつまでも残る。
• アクティビティのonCreate処理が終了後ならstatic な初期化を実行してもよい。
– スレッド注意!
• スレッドはアクティビティでなくプロセスに紐付けられている。アクティビティが生き
続けてる限りスレッドはrunし続ける。
• すべてのネイティブコードはonDestroyでcleanするべし
- 14. ゲームアプリを作るうえで大切なこと
• Input
– キー入力のハンドリング
• onKeyDown/onKeyUp
• dispatchKeyEventのオーバーライドは避けて
• onKeyMultiple/onKeyLongPressも使えるよ
– タッチとマルチタッチのハンドリング
• onTouchEvent
– 内蔵のジェスチャープロセスが使えるよ
– ScaleGestureDetectorとかGestureDetectorとか使ってみて。
• ほとんどの端末が今マルチタッチをサポートしてる
– 端末が異なるポイントを追跡できるかがわかるのはこれ。
– hasSystemFeature(FEATURE_TOUCHSCREEN_MULTITOUCH_DIST
INCT)
• Androidらしいゲームとはハードボタンをうまく使うこと
– Back・・・ダイアログのdissmiss、メニュー終了、ゲームのポーズ
– Menu・・・ポーズ、オプションダイアログ起動
– Home・・・ポーズ(ゲームを終わらせてはいけない!!!)
– ボリュームボタン・・・
setVolumeControlStream(AudioManager.STREAM_MUSIC)
– onPauseやonStopを駆使して可能な限りゲームの状態を保存しよう
- 15. ゲームアプリを作るうえで大切なこと
• Graphics(OpenGL)
– GLSurfaceView
• Context(Dalvikとネイティブコードの間でシェアされる)
• レンダリングをするスレッドを作る
• onPauseの間、コンテキストをリリースしてくれる
• OpenGLでのマルチタスクはもっとも効率的ではないが、いくつか
のドライバが問題を回避する
– Contextがlostしたら
• リソースをリロードする
(Textures,Buffer object, Shaders(シェーダ))
• 名前は保持されない
- 16. ゲームアプリを作るうえで大切なこと
• Texture Formats
– チップセットベンダはいくつかのさまざまなテクスチャの独
自の圧縮フォーマットを使っている
– Open GL ESはマルチ圧縮フォーマットをサポートしてい
る(必須ではない)
– 非圧縮テクスチャ
– ETC1使用(フォトグラフィックデータを最適化、Alpha値は
ない)
– Multi-APK(coming soon)
– asset サーバにテクスチャをおく
• runtimeでの検出サポート
• それぞれの端末でダウンロード
- 17. ゲームアプリを作るうえで大切なこと
• 描画性能
– 描画のオーダーは大切
• 早めの切り離し
– VBOを使う(不必要な状態変化を回避)
– テクスチャ
• 2倍のサイズのテクスチャの電力を使う
– とっても遅い
– いくつかのチップセットで動かない
• 互換性のあるシェーダを書く
• Queryの確認(属性の数、構文など)
– 端末間でさまざま
– 気をつけないとクラッシュするよ
– supported は”performs well”とは意味が違う
• Conditions
– できるだけ使用を避ける。どしても使いたかったらシェーダの最後におく
– 同じ結果を生成するためにmix(),clamp()などを使う
• discard()
– 回避して。使うなら最後に。
- 18. ゲームアプリを作るうえで大切なこと
• Sound
– フル演奏ならMediaPlayer
• コーデックはマルチプルフォーマットサポート
• ファイルシステムやネットワークから再生可能
• すばやいサウンドエフェクトのために、待ち時間、メモリ、CPU使用率な
ど大きくなる
– サウンド効果やクリップならSoundPool
• コーデックはマルチプルフォーマットサポート
• あらかじめ音源ファイルをプールにロードするので待ち時間は少ない
– アプリで音を作るならAudioTrack(PCM音源)
– OpenSL/ES
• MediaPlayerとAudioTrackの便利な機能をあわせもつ
• NDKでのみ使用できる
• Android2.3以上
- 19. ゲームアプリを作るうえで大切なこと
• assets(資産)
– JNI
• APKファイル名の取得
– context.getApplicationInfo.sourceDir
• AssetFileDescriptorのインスタンスを取得
– afd = context.getAssets.openFd(“Hoge.png”);
• AssetFileDescriptorからオフセットや長さがわかる
– long offset = afd.getStartOffset()]
– long length = afd.getDeclaredLength()
– afd.close()
– オフセットを指定してAPKファイルを開き長さを指定してよ
む(オーバヘッドの測定?)
– Zip Utility
– nativeでAssetManagerを使え(Gingerbread以降)
- 21. トラブルシューティング1
解決方法
スレッドを確認してみて!!
JNIの複数のcontextがひとつのスレッドになってない?
ひとつのJNIのcontextにつきスレッドは一本
- 23. トラブルシューティング2
解決方法
ハードが古いんじゃないの?確認して!
ARM5 CPUはOpenGL2サポートしてない
ハードが古くてもクラッシュさせずに動作させたい場合
16bitのテクスチャを使え
BitmapFactory.Options.inPreferredConfig = Bitmap.Config.ARGB_4444
小さい描画ターゲットを使って拡大する
SurficeHolder.setFixedSize()
特にタブレットは高ピクセル。
何をどうやってもクラッシュしてしまう場合は
マーケットでフィルタをかける
命令セット(ARMv5/ARMv7)
GL Version
Platform を古いのに戻す
有効なデバイスを使う
- 24. Tips
• 小さくスタート
• Androidのbackup/restoreを使ってクラウドに保存
– 端末を他に切り替えたときゲームの進捗を保持できる
• 人によって使うコントローラは違うのでどのコントロールデバイスにも対応させる
– トラックボール、D-pad、ジョイスティック
• SDカードへのインストールをサポート
– これをしないとマーケットのユーザ評価が落ちます
• プロファイリング
– 端末ごとに最適な設定を選ぶためにプロファイリングをしよう
• ソーシャル
– OpenIDを使用したソーシャルネットワークを使ってみたら?
• Live Wallpaperにしてみようよ?
– ゲームのアバターと状態をホームスクリーンでもみれるといいよ
• アプリ追跡
– ゲームのマーケティングにいいよ
• アプリ内課金
– 新しい収益の手法を身に付けよう
- 25. はまったときのデバッグ支援ツール
• 開発ツール
– NVIDIA Debug Manager(Eclipse用)
• シンプルな設定で済むEclipse上でのネイティブデバッカ
– WinGDB
• NDKアプリのデバッグにVisual Studio を使う
– www.wingdb.com
– vs-android
• Android ツールチェイン用のネイティブのMSBuild ファイル
– vs-android.googlecode.com
• 性能評価ツール
– NVIDIA PerfHUD ES
• developer.nvidia.com/tegra/perfhud-es
– Adreno Profiler
• developer.qualcomm.com/showcase/adreno-profier
– POWERVR Insider Utilities
• PVRTraceやPVRTuneを含む
– www.imgtec.com/powervr/insider/powervr-utiliyies.asp