android gameprogramming

25
日本Androidの会 日高 正博 2010/10/10 1 日本Androidの会/日高正博

Upload: mhidaka

Post on 28-May-2015

13.302 views

Category:

Documents


4 download

DESCRIPTION

メビック扇町【クリエイティブクラスターフォーラム】スマートフォンフォーラム発表資料/Android開発Tips

TRANSCRIPT

Page 1: Android gameprogramming

日本Androidの会 日高 正博

2010/10/10 1日本Androidの会/日高正博

Page 2: Android gameprogramming

日高 正博(ひだか まさひろ)◦ 日本Androidの会/関西支部

Android開発情報サイト Tech Booster 運営http://techbooster.jpn.org/65記事を超えて週に3本ペースで増殖中!

2

TwitterAccount@mhidaka

2010/10/10日本Androidの会/日高正博

Page 3: Android gameprogramming

1. Androidとゲーム

•概要/スレッド構成/注意点

2. ゲームでの描画

• SurfaceView/時系列処理

3. メモリ管理

• GC/OOM/確保の方法

4. まとめ

2010/10/10 3日本Androidの会/日高正博

Page 4: Android gameprogramming

2010/10/10日本Androidの会/日高正博 4

Page 5: Android gameprogramming

ユーザ体験:“たのしい!”のために。

• AndroidマーケットでGameは2番目の人気

• より高速に、より小さく!大きいゲームはアンインストールされやすい

ユーザレスポンス

•処理には案外時間がかかるものも多い。見せ方を工夫。

•例:処理中であればスピナー/プログレスバーで通知する

•ネットワークアクセス(ライセンスサーバとの通信など)

•スコアの保存やデータのバックアップなど

2010/10/10日本Androidの会/日高正博 5

Page 6: Android gameprogramming

シングル・スレッド・モデル

•Mainスレッド(UI Thread

•Activityに関する処理

•ライフサイクル

•onCreate/OnPause

•各UIパーツ(Viewなど)

の描画処理

デーモンスレッド&

ユーザスレッド

•ユーザスレッド:

処理が終わる(return)まで

プログラムは終了できない

•デーモンスレッド:

プログラム終了時にスレッ

ドの実行終了を待たない

2010/10/10日本Androidの会/日高正博 6

Page 7: Android gameprogramming

描画・ロジック・UIでスレッド分割

•描画/CPU処理などで応答遅延を防ぐ

• タスクの占有はANRの対象(Application

Not Responding)

• リアルタイムゲームであれば

30FPSが理想

•将棋などCPUがんばる系のゲーム

logic大事(Android2.2のJIT?)

• タッチイベント飛び過ぎ

onTouchEventの中でSleepする

2010/10/10日本Androidの会/日高正博 7

UI

•入力、レスポンス

•Activityの処理

logic

•ゲームの論理構造

•無限ループ

グラフィック

•画像処理、エフェクト

•SurfaceView

ユーザ入力TimerEvent

画像処理

画面へのフィードバック

Page 8: Android gameprogramming

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);

Page 9: Android gameprogramming

Android端末のインターフェイス

•キーボード、タッチパネル、センサー、ハードキー

機種が多いので想定が難しい

•スマートフォン? TV ? タブレット?

2010/10/10日本Androidの会/日高正博 9

インターフェイス

変換

キー

ボード

タッチパ

ネル

セン

サー

ハード

キー おすすめはインターフェイスの変換部を持つこと

開発が進んでからでOK

ユーザ・機器に合わせた設定変更が簡単に

logic

input

Page 10: Android gameprogramming

2010/10/10日本Androidの会/日高正博 10

Page 11: Android gameprogramming

Canvas

•描画にかかわる処理をすべてUIスレッドで行う

•以下の2つに比べると低速だけど簡単

SurfaceView

•演算を別スレッドで実施してUIスレッドで描画

•CanvasとSurfaceViewはCPU処理

GLSurfaceView

•OpenGLを使った描画処理を行う。非常に高速。

•ハードウェア処理、機種依存が多少あるので注意。地獄。

2010/10/10日本Androidの会/日高正博 11

Page 12: Android gameprogramming

SurfaceView

•画面(Surface)を描画する専用スレッドを提供する

(資源ロックが発生)

•描画には、SurfaceHolderというインターフェイスを利用

実装

•描画処理はSurfaceHolderのコールバックとして実装する

• SurfaceHolder.Callback.surfaceCreated()

• SurfaceHolder.Callback.surfaceChanged()

• SurfaceHolder.Callback.surfaceDestroyed()

2010/10/10日本Androidの会/日高正博 12

Page 13: Android gameprogramming

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のコンストラクタ

Page 14: Android gameprogramming

//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

Page 15: Android gameprogramming

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();}

}

Page 16: Android gameprogramming

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;}

(省略)}

}

Page 17: Android gameprogramming

代表的なレイアウトは4つ

2010/10/10日本Androidの会/日高正博 17

Page 18: Android gameprogramming

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));

}

Page 19: Android gameprogramming

2010/10/10日本Androidの会/日高正博 19

Page 20: Android gameprogramming

ガベージコレクション

• 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

Page 21: Android gameprogramming

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

Page 22: Android gameprogramming

Androidのメモリは潤沢ではない◦ 自分が使うメモリ量を計算する

リアルタイムゲームでは開始前に全部のデータを読み込むといい。◦ マップデータ、シナリオ、音声、キャラクターなどなど。

メモリリークに気をつける

◦ 意図せずオブジェクトが解放されなくてメモリを握ったままになることも。

◦ 手っ取り早いのはDDMSでメモリ量を確認。パフォーマンス計測はLog.dやTraceViewもおすすめ。

2010/10/10日本Androidの会/日高正博 22

Page 23: Android gameprogramming

2010/10/10日本Androidの会/日高正博 23

Page 24: Android gameprogramming

ユーザインターフェイス

• レスポンスを大事に。入力デバイスを選べるように。

•ゲームロジックを分割してマルチスレッド化

View

•描画はゲーム特性に合わせて最適なものを。

•ボードゲーム:Canvas、リアルタイム系:OpenGL/SurfaceView

メモリ管理

• GCが走るとゲームは止まる

• メモリ使用量を把握する、リークはDDMS/MATなどで確認

2010/10/10日本Androidの会/日高正博 24

Page 25: Android gameprogramming

ご清聴ありがとうございました

2010/10/10 25日本Androidの会/日高正博