android gameprogramming
DESCRIPTION
メビック扇町【クリエイティブクラスターフォーラム】スマートフォンフォーラム発表資料/Android開発TipsTRANSCRIPT
日本Androidの会 日高 正博
2010/10/10 1日本Androidの会/日高正博
日高 正博(ひだか まさひろ)◦ 日本Androidの会/関西支部
Android開発情報サイト Tech Booster 運営http://techbooster.jpn.org/65記事を超えて週に3本ペースで増殖中!
2
TwitterAccount@mhidaka
2010/10/10日本Androidの会/日高正博
1. Androidとゲーム
•概要/スレッド構成/注意点
2. ゲームでの描画
• SurfaceView/時系列処理
3. メモリ管理
• GC/OOM/確保の方法
4. まとめ
2010/10/10 3日本Androidの会/日高正博
2010/10/10日本Androidの会/日高正博 4
ユーザ体験:“たのしい!”のために。
• AndroidマーケットでGameは2番目の人気
• より高速に、より小さく!大きいゲームはアンインストールされやすい
ユーザレスポンス
•処理には案外時間がかかるものも多い。見せ方を工夫。
•例:処理中であればスピナー/プログレスバーで通知する
•ネットワークアクセス(ライセンスサーバとの通信など)
•スコアの保存やデータのバックアップなど
2010/10/10日本Androidの会/日高正博 5
シングル・スレッド・モデル
•Mainスレッド(UI Thread
•Activityに関する処理
•ライフサイクル
•onCreate/OnPause
•各UIパーツ(Viewなど)
の描画処理
デーモンスレッド&
ユーザスレッド
•ユーザスレッド:
処理が終わる(return)まで
プログラムは終了できない
•デーモンスレッド:
プログラム終了時にスレッ
ドの実行終了を待たない
2010/10/10日本Androidの会/日高正博 6
描画・ロジック・UIでスレッド分割
•描画/CPU処理などで応答遅延を防ぐ
• タスクの占有はANRの対象(Application
Not Responding)
• リアルタイムゲームであれば
30FPSが理想
•将棋などCPUがんばる系のゲーム
logic大事(Android2.2のJIT?)
• タッチイベント飛び過ぎ
onTouchEventの中でSleepする
2010/10/10日本Androidの会/日高正博 7
UI
•入力、レスポンス
•Activityの処理
logic
•ゲームの論理構造
•無限ループ
グラフィック
•画像処理、エフェクト
•SurfaceView
ユーザ入力TimerEvent
画像処理
画面へのフィードバック
AsyncTask◦ 非同期処理
Runnable,Thread◦ Javaマルチスレッド処理(同期、優先度制御etc)が可能◦ Runnableインターフェイス、Threadクラス。あとで解説します
2010/10/10日本Androidの会/日高正博 8
メソッド名 内容
onPreExecute() 事前準備の処理を記述する
doInBackground(Params...) バックグラウンドで行う処理を記述する
onProgressUpdate(Progress...) 進捗状況をUIスレッドで表示する処理を記述する
onPostExecute(Result) バックグラウンド処理が完了し、UIスレッドに反映する処理を記述する
public class MonochromeTask extends AsyncTask<Bitmap, Integer, Bitmap> {
@Overrideprotected Bitmap doInBackground(Bitmap... bitMap) {
Bitmap outBitMap = bitMap[0].copy(Bitmap.Config.ARGB_8888, true);
Android端末のインターフェイス
•キーボード、タッチパネル、センサー、ハードキー
機種が多いので想定が難しい
•スマートフォン? TV ? タブレット?
2010/10/10日本Androidの会/日高正博 9
インターフェイス
変換
キー
ボード
タッチパ
ネル
セン
サー
ハード
キー おすすめはインターフェイスの変換部を持つこと
開発が進んでからでOK
ユーザ・機器に合わせた設定変更が簡単に
logic
input
2010/10/10日本Androidの会/日高正博 10
Canvas
•描画にかかわる処理をすべてUIスレッドで行う
•以下の2つに比べると低速だけど簡単
SurfaceView
•演算を別スレッドで実施してUIスレッドで描画
•CanvasとSurfaceViewはCPU処理
GLSurfaceView
•OpenGLを使った描画処理を行う。非常に高速。
•ハードウェア処理、機種依存が多少あるので注意。地獄。
2010/10/10日本Androidの会/日高正博 11
SurfaceView
•画面(Surface)を描画する専用スレッドを提供する
(資源ロックが発生)
•描画には、SurfaceHolderというインターフェイスを利用
実装
•描画処理はSurfaceHolderのコールバックとして実装する
• SurfaceHolder.Callback.surfaceCreated()
• SurfaceHolder.Callback.surfaceChanged()
• SurfaceHolder.Callback.surfaceDestroyed()
2010/10/10日本Androidの会/日高正博 12
2010/10/10日本Androidの会/日高正博 13
public class surfaceViewActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);setContentView(new sampleSurfaceView(this));
}}
private Bitmap mImage;
//コンストラクタpublic sampleSurfaceView(Context context) {
super(context);
getHolder().addCallback(this);mImage = BitmapFactory.decodeResource(getResources(),
R.drawable.bakeneko);}
ActivityにViewを設定
SurfaceViewのコンストラクタ
//SurfaceView生成時に呼び出される
public void surfaceCreated(SurfaceHolder holder) {
//初期描画(生成タイミングで描画する必要があるもの)
//Canvasの取得(マルチスレッド環境対応のためLock)
Canvas canvas = holder.lockCanvas();
Paint paint = new Paint();
paint.setTextSize(24);
paint.setColor(Color.WHITE);
//描画処理(Lock中なのでなるべく早く)
canvas.drawBitmap(mImage, 0, 0, paint);
canvas.drawText("TechBooster",0,200,paint);
//LockしたCanvasを解放、ほかの描画処理スレッドがあればそちらに。
holder.unlockCanvasAndPost(canvas);
}
2010/10/10日本Androidの会/日高正博 14
SurfaceView生成logic
Runnableインターフェイス
•ユーザスレッドの作成。別スレッドで時間、移動量を決定
2010/10/10日本Androidの会/日高正博 15
public class sampleSurfaceView extends SurfaceViewimplements SurfaceHolder.Callback, Runnable{
private Thread mLooper;
(省略)}
//SurfaceView生成時に呼び出されるpublic void surfaceCreated(SurfaceHolder holder) {
//スレッドの生成mHolder = holder;mLooper = new Thread(this);
}
//SurfaceView変更時に呼び出されるpublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//スレッド処理を開始if(mLooper != null ){
mLooper.start();}
}
RunnableインターフェイスのRunメソッド
2010/10/10日本Androidの会/日高正博 16
//スレッドによるSurfaceView更新処理public void run() {
while (mLooper != null) {
//描画処理doDraw();
//位置更新処理//処理落ちによるスローモーションをさけるため現在時刻を取得long delta = System.currentTimeMillis() - mTime;mTime = System.currentTimeMillis();
//次の描画位置int nextPosition = (int)( ( delta / 1000.0 ) * 200 ); //1秒間に200px動くとして
//描画範囲の設定if(mPositionTop + nextPosition < mHeight ){
mPositionTop += nextPosition;}
(省略)}
}
代表的なレイアウトは4つ
2010/10/10日本Androidの会/日高正博 17
FrameLayoutで上から描画を重ねる
2010/10/10日本Androidの会/日高正博 18
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
FrameLayout frameLayout = new FrameLayout(this);setContentView(frameLayout);
frameLayout.addView(new sampleSurfaceView(this),new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//サンプル表示用のボタンを作成Button button = new Button(this);button.setText("Start Button");frameLayout.addView(button, new
ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
2010/10/10日本Androidの会/日高正博 19
ガベージコレクション
• JavaHeapが足りなくなるとメモリ確保のためGCが走る
•一度GCすると100~200msはゲームが止まる
2010/10/10日本Androidの会/日高正博 20
05-14 17:43:25.916: DEBUG/dalvikvm(51): GC freed 637 objects / 29528 bytes in 86ms
Activityがメモリを食いつぶす
•利用可能なメモリは24MB。かならずこの範囲に収める
OutOfMemoryError
•GCによるメモリ・アロケーション時。
JavaHeap内で、要求サイズ分の空きが無ければ発生
2010/10/10日本Androidの会/日高正博 21
05-14 17:16:45.035: INFO/ActivityManager(51): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=2/1/2 nav=3/1 orien=1 layout=18}05-14 17:16:45.075: ERROR/dalvikvm-heap(187): 2457600-byte external allocation too large for this process.05-14 17:16:45.075: ERROR/(187): VM won't let us allocate 2457600
bytes…省略…05-14 17:16:45.204: ERROR/AndroidRuntime(187): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
Androidのメモリは潤沢ではない◦ 自分が使うメモリ量を計算する
リアルタイムゲームでは開始前に全部のデータを読み込むといい。◦ マップデータ、シナリオ、音声、キャラクターなどなど。
メモリリークに気をつける
◦ 意図せずオブジェクトが解放されなくてメモリを握ったままになることも。
◦ 手っ取り早いのはDDMSでメモリ量を確認。パフォーマンス計測はLog.dやTraceViewもおすすめ。
2010/10/10日本Androidの会/日高正博 22
2010/10/10日本Androidの会/日高正博 23
ユーザインターフェイス
• レスポンスを大事に。入力デバイスを選べるように。
•ゲームロジックを分割してマルチスレッド化
View
•描画はゲーム特性に合わせて最適なものを。
•ボードゲーム:Canvas、リアルタイム系:OpenGL/SurfaceView
メモリ管理
• GCが走るとゲームは止まる
• メモリ使用量を把握する、リークはDDMS/MATなどで確認
2010/10/10日本Androidの会/日高正博 24
ご清聴ありがとうございました
2010/10/10 25日本Androidの会/日高正博