2011年7月22日金曜日

SurfaceViewを試す (SurfaceView Example)

@ITの連載記事 SurfaceViewならAndroidで高速描画ゲームが作れる のサンプルを試しながらSurfaceViewに関して学んでみたり。

途中で気がついたんですが、連載のサンプルはAndroid2.0(API level5)ベースみたいですね。Android1.6(API level4)で試してたので、そのままでは動かないところがありました。

android:theme="@android:style/Theme.Wallpaper"

ってListViewの背景をホーム画面の背景にあわせる設定が利かないとか。仕方ないので適当な画像を用意して設定しました。

listView.setBackgroundResource(R.drawable.rgm79c);


また1.6で抽象クラスだったのが2.0で実装されたのか、@Overrideが軒並みエラーになっていたので削除してみたり。設定の違いかもしれませんが。

この状態でViewを透過させる Transparent SurfaceView などのサンプルは問題なく動作しました。なかなか面白いですね。


また Offscreen はゲームなどに必須のダブルバッファリングに関するサンプルで、非常に参考になりました。ただこのサンプル、

Canvas canvas = holder.lockCanvas();
/* ここに osb の更新処理 */
canvas.drawBitmap(osb, 0, 0, null);
holder.unlockCanvasAndPost(canvas);

ってなっていて、lockCanvas()が名前どおりのロックする関数だったら、ダブルバッファリングの意味が薄い気がw

/* ここに osb の更新処理 */
Canvas canvas = holder.lockCanvas();
canvas.drawBitmap(osb, 0, 0, null);
holder.unlockCanvasAndPost(canvas);

と修正しておきました。これが正しい… ですよね?たぶん…

もっとも解説には「Androidではフレームワークが内部でダブルバッファリングを行ってくれるため、オフスクリーンバッファを持たなくてもよくなりました」とありますので、このへんは気にしなくて良い部分かもしれません。

実際、ちょっと描画を重くしてフレームレートを表示させてみましたが、Offscreen/NoOffscreen サンプル共にあまり違いが感じられませんでした。


解説にもありますが、Offscreen手法はあくまで他の環境用のアプリとロジックなどを共用する場合にのみ使えば良いのかもしれませんね。

で、最後は入力系のイベント処理です。まず、タッチ入力の処理が笑っちゃうほどシンプルなので転載します。

public boolean onTouchEvent(MotionEvent event) {
  left = event.getX();
  top = event.getY();
  doDraw();
  return true;
}
void doDraw() {
  Canvas canvas = getHolder().lockCanvas();
  canvas.drawBitmap(bitmap, left, top, null);
  getHolder().unlockCanvasAndPost(canvas);
}

セットアップなど必要ですが、基本これだけで↓が動くのはなかなかです。


そして定番の、カーソルでオブジェクトを動かす GameSample ですね。自身でRunnableを実装して

public void run() {
  while (true) { doDraw(); }
}

し続けてonKeyイベントの結果を反映させ続けるという、漢気あふれる作りに目を奪われますが、カーソルでロボット君を自在に動かすのは楽しいものです。


とりあえずSurfaceViewに関して、最低限は使えるようになった気がします。

0 件のコメント:

コメントを投稿