androidでゲームアプリ制作 -2ページ目

androidでゲームアプリ制作

androidアプリ開発の記録です.
覚書メインです。
書かれている内容が確実に正しいという保証はありません。

Canvasへの描画で、部分的に消去したい場合は、描画に用いるPaintの設定を変えることで実現できる。


eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));


このPaintを用いてCanvasに描画すれば、描画範囲が消去される。

参考リンク
キャプチャ画像を取る方法(大ハマリ)
ページ内の【消しゴム機能】 の項
マップチップ等を用いて、複数の画像を組み合わせて表示したい場合、
バックグラウンドで画像を編集しておく必要がある。

BitmapオブジェクトをCanvasに与えて、Canvasから描画を行うことで実現できる。

今回は
「1つの矢印が描かれた画像を30度刻みで回転させながらコピーして、12個の矢印が横に並んだBitmapを生成する」を実現する。

●空のBitmapの生成とCanvasの準備


arrows = Bitmap.createBitmap(arrowOrg.getWidth() * 12, arrowOrg.getHeight(), Bitmap.Config.ARGB_8888);
Canvas arrowCanvas = new Canvas(arrows);



・Bitmap arrows
最終的に12個の矢印が並ぶBitmap
・Bitmap arrowOrg
元の矢印のBitmap
・Canvas arrowCanvas
arrowsを編集するためのキャンバス

Bitmap.createBitmapで空のBitmapオブジェクトが生成できる。
第1引数は幅、第2引数は高さ、第3引数はコンフィグ。コンフィグでは色のモードなどを決めることができる。
Canvasのコンストラクタの引数に編集したいBitmap(今回はarrows)を与える。

●Bitmapを編集する


arrowCanvas.drawColor(Color.WHITE);
Matrix m = new Matrix();
Rect src = new Rect(0, 0, arrowOrg.getWidth(), arrowOrg.getHeight());
Rect dst = new Rect(0, 0, arrowOrg.getWidth(), arrowOrg.getHeight());
for (int i = 0; i < 12; i++) {
arrowCanvas.drawBitmap(Bitmap.createBitmap(arrowOrg, 0, 0, arrowOrg
.getWidth(), arrowOrg.getHeight(), m, false), src, dst, p);
dst.set(dst.left + arrowOrg.getWidth(), dst.top, dst.right
+ arrowOrg.getWidth(), dst.bottom);
m.postRotate(30);


・Matrix m
Bitmapの変形(今回は回転)のための行列
・Rect src,dst
Bitmapのコピー元、コピー先の矩形

まずは、Canvas.drawColorでBitmapを白で塗りつぶす。
次に、Matrixと矩形オブジェクトの準備
for文の中で、12回Bitmapの回転とコピーを行っている。

Canvas.drawBitmapで、CanvasにBitmapをコピーすることが出来る。そのコピー元のBitmapは
Bitmap.createBitmapで生成しているが、この時第6引数のMatrixで変形をしている。

Matrix.postRotateで変形の回転角を追加することができる。引数は角度で指定(360°で一周する方)また、「追加」であることに注意。
同じMatrixにpostRotate(30)を二回実行するとその行列は60度の回転が指定されていることになる。


参考リンク
グラフィックス(6)-Bitmapの描画とMatrixの操作
[Android] 動的に作成した Bitmap を編集する方法
●可変fpsで入力

アクションゲームなどでは、ボタンを押している間だけ、自機が移動したり回転したりする処理を行う必要がある。

ボタンに入力の変化(押した、離した、ドラッグした等)があると、onTouchイベントが起こるが、その中でアニメーションの変化を実装すると、描画のループ速度とイベントの発生間隔の違いが問題になる(描画と入力が別のスレッドで処理されているため)。

そこで、onTouchイベント内では入力の状態のパラメータだけを変更して、描画時にそのパラメータの状態を参照するようにする。

以下ではアクションゲームにおける「ボタンが押されている間だけ自機が回転し、ボタンを離すと回転が止まる」という機能を実装する。

ボタン側

buttonL.setOnTouchListener(new OnTouchListener(
) {

public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
gameView.turnLeft();
break;
case MotionEvent.ACTION_UP:
gameView.turnReset();
break;
}

return false;
}
});

MotionEventのgetActionメソッドでボタンに対するアクションを得られる。
そのアクションによってボタンの押した時、離した時の処理を実装できる。

View側

public void turnLeft() {
isRight = false;
isLeft = true;
}

public void turnReset() {
isRight = false;
isLeft = false;
}

ボタン入力では、真理値型のパラメータの変更だけを行う。


描画ループ内

if (isLeft)
theta = theta - (Math.PI * (delta / 1000.0));

ボタンが押されている場合にif文の中が処理されるようになっている。

thetaは自機の回転角(ラジアン)、この角の正弦、余弦をとって移動先の座標を決める。
deltaは1回の描画にかかる時間(ミリ秒)である。
代入文の右辺の第2項は「1秒間ボタンを押すと半回転する」を実現している。

つまり、1回の描画すなわちdeltaが1秒(=1000ミリ秒)かかる場合第2項はπとなり、半回転となるようになっている。

1回の描画が50ミリ秒かかる場合、deltaは50となる、その時第2項はπ/20である。
その時1秒間に20回の描画が行われる(delta * 20 = 1000ミリ秒)。1回の描画の度に
π/20回転されるので、1秒間で半回転(=π)の描画が実現できるのである。

参考URL
タッチイベントを取得する(onTouchEventとMotionEvent)
タッチイベントを取得する