2Dタイルマップを使用するゲームに取り組んでいます。マップは、SurfaceViewのカスタムメソッドdoDraw()を介してレンダリングされます。これは、2D配列からタイルタイプを取得し、そのタイプに対応するビットマップを決定してから、指定された座標でタイルをキャンバスに描画する単純なdoubleforループです。
以前は、ドローアブルフォルダにプレースホルダー.pngがありました。これらのプレースホルダードローアブルは、msペイントで作成した単色の単純な100x100.pngファイルでした。プレースホルダーのドローアブルをいくつかの素敵なテクスチャのドローアブルと交換するまでは、問題なく機能しているように見えました。次に、タイルを描画するために座標を参照する方法が正しくなく、実際にそれらがオーバーラップしていることに気付きました。タイルが無地の場合、これは明らかではありませんでしたが、テクスチャを使用すると、タイルの2つの側面が隣接するタイルで覆われていることがかなり明らかになりました。
問題は実際には私のdoDraw()メソッドにあるのではなく、タイルサイズを参照している方法にある可能性が高いと思います。.pngファイルは100x100ですが、デバイスのピクセル密度に基づいて、おそらく別のサイズに変換されています。私はそれが起こっていると思います、そして私はそれに対処する方法を読んでいます、しかし私がそこで見つけているすべては一般に単一のビットマップについて話しているでしょう、お互い。
これが私のSurfaceViewからの関連コードです:
public class MapView extends SurfaceView implements SurfaceHolder.Callback {
protected Context context;
public World world;
public Map<Integer,Bitmap> TILE_MAP;
public Bitmap SPRITE;
public Player player;
public Camera camera;
//hardcoded parameters for testing
private int tile_width = 50;
private int tile_height = 50;
public int screen_width = 12; //specifies how many tiles to draw in y direction
public int screen_height = 6; //specifies how many tiles to draw in x direction
public MapThread mapThread;
public MapView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
Log.d("LOGCAT", "MapView created");
//get the tile map
WorldFeatures worldFeatures = new WorldFeatures(context);
TILE_MAP = worldFeatures.TILE_MAP;
SPRITE = worldFeatures.SPRITE;
SurfaceHolder holder = getHolder();
holder.addCallback(this);
}
public void doDraw(Canvas canvas) {
/*the draw method looks a little muddled at the moment as my camera is referencing
the center tile instead of the top left tile. I'll be updating that soon*/
int screenX = 0; //reset screenX each loop
for (int worldX = (camera.x - screen_height/2 + 1); worldX < (camera.x + screen_height/2 + 1); worldX += 1, screenX += 1) {
int screenY = 0; //reset screenY each loop
for (int worldY = (camera.y - screen_width/2 + 1); worldY < (camera.y + screen_width/2 + 1); worldY += 1, screenY += 1) {
canvas.drawBitmap(TILE_MAP.get(world.world_map[worldX][worldY]), screenY*tile_height , screenX*tile_width, null);
if (player.x == worldX && player.y == worldY) { //if the player is standing here, draw the sprite
canvas.drawBitmap(SPRITE, screenY*tile_height + tile_height/5, screenX*tile_width + tile_width/5, null);
}
}
}
}
}
上記のように、タイルの高さと幅をハードコーディングしました。これを抽象化する手段があればいいのですが、まず、使用する正しい数字が何であるかを理解したいと思います。タイルの高さと幅を100に設定すると、タイルの間にスペースができます。50に設定すると、オーバーラップします。これは、参照する正しいサイズがその中間にあることを示しています。正しくなるまで推測を続けることができましたが、ドローアブルがどのピクセル密度に対してどのサイズにスケーリングするかを決定する方法を理解したいと思います。
現在、私のドローアブルは私のドローアブル-hdpiフォルダーにあり、他のどこにもありません。それらを一般的な「描画可能」フォルダーに配置するかどうか疑問に思っていますが、tile_heightとtile_widthを100x100として参照できますか?固有の高さと幅を取得する方法について読みましたが、ビューまたはデバイス用にビットマップをスケーリングする場合は役に立ちません。元のドローアブルサイズに基づいてタイルサイズを参照することは可能だとしても、特定の数で参照するよりも良い方法があると思います。描画メソッド内で、スケーリングされたサイズを確認できませんか?そして、それを使用して、タイルを描画する座標を決定しますか?さらに良いことに、キャンバスに描画する前に、ビットマップをどのサイズに拡大縮小するかを強制する方法はありますか?
http://developer.android.com/guide/practices/screens_support.htmlでピクセル密度、dpi、描画可能なフォルダーなどを読んだことがありますが、これは、お互いに、したがって座標が必要です。
また、Rectanglesを入力として受け取るCanvasのdrawbitmap()メソッドはピクセル密度に依存しないため、Rectanglesを使用してキャンバスに描画することも検討しました。しかし、12x6のタイルのセットを描画する場合、長方形を使用することがどれほど実用的かはわかりません。タイルの場所ごとに1つの長方形が必要ですか?
スケーリングされたビットマップの処理や、私が描いているものを描くためのより良い方法についての説明が最も役立ちます。