「Galaxy Tab」でチップセット画像が崩れる際の対応方法 - 「Ex Reversi」を「Galaxy Tab」に対応させた時のメモ
はじめに
Android版の「Ex Reversi」は、2009年の4月にリリースしたアプリケーションです。
この「Ex Reversi」は、変形盤面を指すことができるアルゴリズムを搭載しています。このアルゴリズムは「n次元の変形盤面リバーシ」を指すためのアルゴリズムとして、2000年に柳井政和によって考案されました。このアルゴリズムを、高速化のために2次元に限定してJAVAに実装したのが「Ex Reversi」のエンジン部分になります。
このAndroid版の「Ex Reversi」ですが、ちょうどAndroid 1.5の頃に開発され、その後何度かのバージョンアップを重ねてきました。今回、Android 2.3の「ADK」に、「Galaxy Tab」の「AVD」が同梱されていたので、対応させることにしました。
結論から言うと、そのまますんなりとは動きませんでした。1.5の頃に書いたプログラムということもあり、現状の環境を想定していなかった部分もあり、予想外の動きをしました。そこで本稿では、発生した問題と、行なった対処をまとめておきます。
同じような問題に遭遇した人の一助になればと思います。
「Galaxy Tab」への対応1
まず、プログラムを「Galaxy Tab」に対応させるために、「AndroidManifest.xml」の設定を変更しました。
「Ex Reversi」は、Androidの1.5以降を対象にしていました。そのため、「AndroidManifest.xml」の「minSdkVersion」を「3」に設定していました。この場合、「Galaxy Tab」で、画面は表示されますが、「320×480」という小さなサイズで表示され、かつその周囲に余白が出てしまいます。結果として、何も表示されない黒い領域が、画面に多く残ってしまいます。
これは、1.5の設定では、画面サイズが対応していないためです。
そこで、まずは「minSdkVersion」を「4」にしました。すると、画面いっぱいにアプリケーションの描画が行なわれるようになりました。しかし、ここで問題が発生しました。
画像のうち、チップセットとして用意していた画像の表示が「崩れる」(正しく表示されない)という問題が発生したのです。
発生した問題の原因
原因は2つありました。
原因1
1つ目の原因は「BitmapFactory.decodeResource(Resources res, int id)」というメソッドを使うと、画像をリソースから読み込む際に、自動で画像がリサイズされてしまうことです。
マップ画面などによく使われるチップセット用の画像は、複数の画像を1枚の画像としてまとめています。そして、画像の読み込み位置と、切り取り位置を指定して、切り貼りしながら、画面に画像を描画します。
このチップセットのサイズが自動でリサイズされると、参照位置がおかしくなり、かつ切り取り範囲も誤った場所になります。この結果として、画像が「崩れて」しまいます。
原因2
2つ目の原因は、「canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint)」メソッドで画像を描画する際に、画像が自動でリサイズされて描画されることです。
このため、例えば「40ドット×40ドット」のサイズとして作成した画像を画面に描画すると、「60ドット×60ドット」の範囲に拡大されて描画されてしまいます(「Galaxy Tab」では1.5倍にリサイズされていました)。
この問題は、画像をタイル状に敷き詰める処理を行う際に問題になります。40×40の画像を画面上に敷き詰めたつもりが、自動で60×60に拡大されて描画されてしまうので、意図しない表示結果になってしまいます。
解説
このような、画像の自動リサイズは、通常のアプリケーションでは便利な機能かもしれませんが、ゲームでは逆に問題を引き起こします。
以下、この2つの問題を解決する方法を書きます。
「Galaxy Tab」の画像読み込みへの対応
画像を、自動でリサイズすることなく読み込むには、以下のようなプログラムを書きます。
BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inScaled = false; Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.hoge, opt);
「BitmapFactory.Options」を使い、「inScaled」フラグに「false」を設定して、「decodeResource()」の引数に設定すれば、リサイズを行なわずに画像を読み込むことができます。
「Galaxy Tab」の画像描画への対応
「canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint)」メソッドは、デバイスによっては、画像をリサイズして描画します。このリサイズ機能を使わずに描画を行なうには、画像の描画サイズを明示的に指定するとよいです。以下、その方法をコードで示します。
まずは、メソッド外の変数を示します。
Rect mRctSrc = new Rect(); RectF mRctFDst = new RectF();
次に、メソッド内の変数を示します。
int w = mBitmap.getWidth(); int h = mBitmap.getHeight(); mRctSrc.set(0, 0, w, h); mRctFDst.set(x, y, x + w, y + h); canvas.drawBitmap(mBitmap, mRctSrc, mRctFDst, mPaint);
また、リサイズされたサイズを取得したい場合は、以下の方法で取得できます。
int sW = mBmp.getScaledWidth(canvas); int sH = mBmp.getScaledheight(canvas);
まとめ
通常の画面サイズのデバイスでも「Galaxy Tab」でも、「BitmapFactory.Options()」の「inScaled」は「true」になっています。しかし、通常の画面サイズでは画面のリサイズは行なわれませんが、そうでないデバイスでは画像がリサイズされます。
今回、「Ex Reversi」は、古いプログラムだったために、こういった画面サイズが考慮されていませんでした。
(Androidの仕様としては前からあったけど、デバッグ環境がなかったので見落とされていた)
同じようなケースで引っ掛かる人は、それほど多くはないとは思いますが、何かの参考になるかもしれないので、情報をまとめておきます。