0

我正在开发一款使用 2D 平铺地图的游戏。地图是通过 SurfaceView 中的自定义方法 doDraw() 呈现的。这是一个简单的 double for 循环,它从 2D 数组中获取 tile 类型,确定该类型的相应位图,然后在指定坐标处将 tile 绘制到画布上。

以前我的可绘制文件夹中有占位符 .pngs。这些占位符可绘制对象是我在 ms paint 中创建的简单的 100x100 .png 纯色文件。在我用一些漂亮的纹理绘图替换占位符绘图之前,一切似乎都很好。然后我意识到我引用坐标来绘制瓷砖的方式是不正确的,实际上导致它们重叠。当瓷砖是纯色时,这并不明显,但随着纹理的出现,瓷砖的两侧被相邻的瓷砖覆盖变得非常明显。

我相信问题实际上不在于我的 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,我会得到重叠。这告诉我要参考的正确尺寸介于两者之间。我可以一直猜测,直到我猜对了,但我想了解如何确定我的可绘制对象缩放到什么像素密度。

目前,我的可绘制对象位于我的 drawable-hdpi 文件夹中,没有其他地方。我想知道如果我把它们放在一个通用的“可绘制”文件夹中,我能否将 tile_height 和 tile_width 引用为 100x100?我已经阅读了有关获取固有高度和宽度的信息,但是当为视图或设备缩放位图时,这无济于事。即使可以根据原始可绘制尺寸以某种方式引用瓷砖尺寸,我认为应该有比通过任何特定数字引用它们更好的方法。在我的绘制方法中,我不应该能够找出缩放的大小吗?然后用它来确定将瓷砖绘制到什么坐标?更好的是,在将位图绘制到画布之前,有没有办法强制我希望位图缩放到什么大小?

我已经在http://developer.android.com/guide/practices/screens_support.html阅读了像素密度、dpi、可绘制文件夹等信息,但是当我绘制相对于彼此,因此需要坐标。

我还研究了使用 Rectangles 绘制到画布,因为 Canvas 的 drawbitmap() 方法将 Rectangles 作为输入不依赖于像素密度。但是我不确定当我有一组 12x6 的瓷砖要绘制时,使用 Rectangles 会有多实用。每个图块位置需要一个矩形吗?

任何关于处理缩放位图和/或更好的方法来绘制我正在绘制的东西的解释都是最有帮助的。

4

1 回答 1

1

睡觉后回答了我自己的问题。要在 android 自动缩放后获取位图的高度,请在位图上使用 getWidth() 和 getHeight()。要强制位图缩放到特定大小,请使用 scaleBitmap()

于 2013-01-21T00:45:51.173 回答