連載
» 2009年12月08日 00時00分 公開

Androidで動く携帯Javaアプリ作成入門(12):SurfaceViewならAndroidで高速描画ゲームが作れる (2/3)

[緒方聡,株式会社イーフロー]

Androidのグラフィックスに関する重要なポイント

 SurfaceViewの基本が分かったところで、関連する重要なクラスとメソッドをまとめておきます。

表1 SurfaceViewに関連する重要なクラスとメソッド
SurfaceView
SurfaceHolder getHolder() SurfaceHolderを取得
SurfaceHolder
void addCallback(SurfaceHolder.Callback) コールバックを設定
removeCallback(SurfaceHolder.Callback) コールバックを解除
Canvas lockCanvas() 描画を開始
void unlockCanvasAndPost(Canvas) 描画を終了
Canvas
int save() 状態を保存
void restore() 状態を復元
Paint
setAntiAlias(boolean) アンチエイリアスを設定

SurfaceHolderのメソッド

 SurfaceHolderのlockCanvas()には、オーバーロードされたメソッドlockCanvas(Rect)があり、そちらは描画範囲を限定する場合に使用します。描画範囲は、狭ければ狭いほど高速に描画が完了するので、可能なら使うとよいでしょう。

Canvasのメソッド

 Canvasのメソッドsave()とrestore()は、Java SEやJava MEのCanvasにはない概念なので、紹介しておきます。

 Canvas#save()は呼び出された状態を内部スタックに保存し、Canvas#restore()でスタックから保存された状態を復元します。下記サンプルは状態保存後、45度回転させて文字を描画し、元の状態に戻しています。

void doDraw() {
    Canvas canvas = getHolder().lockCanvas();
    canvas.save(); // ★ここで状態を保存
    canvas.rotate(45.0f);
    Paint paint = new Paint();
    canvas.drawColor(Color.WHITE);
    paint.setColor(Color.BLUE);
    paint.setAntiAlias(true);
    paint.setTextSize(24);
    canvas.drawText("Hello, SurfaceView!", paint.getTextSize(), 0, paint);
    canvas.restore(); // ★ここで状態を復元
    getHolder().unlockCanvasAndPost(canvas);
}

 こうすることで、文字だけが45度回転して描画されたことになります。

図2 「ホーム画面に追加」メニュー 図2 Canvasのsave()とrestore()の応用

 状態はスタックに保存されるので、繰り返しsave()を呼び出しても構いません。保存される状態は、クリップマトリックスです。保存する状態を選択するsave(int)、状態をまとめて戻すrestoreToCount(int)などもあります。

Paintのメソッド

 Paintクラスにあるアンチエイリアス機能は、速度とのトレードオフですが、特に文字列描画の際には設定した方がいいでしょう。

図3 AppWidgetのライフサイクル 図3 アンチエイリアス

 図3はアンチエイリアスを設定した場合としていない場合のサンプルです。テキストは上段がアンチエイリアスなし、下がアンチエイリアスありです。視認性がかなり向上しているのが分かると思います。

 画像にもアンチエイリアスを掛けられます。中央のカップケーキが原寸大、右下がアンチエイリアスなし、左下がアンチエイリアスありです。それぞれ4倍に拡大しています。

Androidはダブルバッファリングもやってくれる

 Javaでjava.awt.Graphicsクラスを扱ったことがあるなら、ダブルバッファリングの重要性はご存じかと思います。

 ダブルバッファリングを行わないと、描画時に画面がちらついてしまいます。このテクニックは、Java AppletのころからJava SEでもJava MEでも必須でしたが、Androidではフレームワークが内部でダブルバッファリングを行ってくれるため、オフスクリーンバッファを持たなくてもよくなりました。

図4 「2」というジェスチャー 図4 オフスクリーンバッファを持たない描画

 勘の良い方は気が付いているかもしれませんが、SurfaceHolderのlockCanvas()メソッドはスレッドセーフに作られています。要するに、ほかのスレッドでlockCanvas()が呼ばれると、もう一方のスレッドは、unlockCanvasAndPost(Canvas)が呼び出されるまで描画を行えません。その待っている間にオフスクリーンに描画を済ませてしまう、というのはテクニックの1つです。

 また、iアプリMIDPからアプリを移植する際には、オフスクリーンを持つ構造にしておくと、移植の際の手間やバグが減るでしょう。iアプリやMIDPについては、下記記事と連載をご参照ください。

 次ページでは、UIイベントを駆使した描画と背景を透過させる方法について解説します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。