我正在开发一款使用2D平铺地图的游戏。地图通过SurfaceView中的自定义方法doDraw()呈现。它是一个简单的double for循环,它从2D数组中获取tile类型,确定该类型的相应位图,然后在指定的坐标处将tile绘制到画布。
以前我的drawable文件夹中有占位符.pngs。这些占位符drawables是我在ms画中创建的简单的100x100 .png纯色文件。事情似乎工作正常,直到我用一些漂亮的纹理drawables换掉占位符drawables。然后我意识到我引用坐标绘制瓷砖的方式是不正确的,实际上是导致它们重叠。当瓷砖是纯色时,这一点并不明显,但是有了纹理,很明显瓷砖的两面被相邻的瓷砖覆盖。
我认为问题实际上不在我的doDraw()方法中,但最有可能的方式是我引用了tile大小。 .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,我会重叠。这告诉我正确的引用大小介于两者之间。我可以继续猜测,直到我做对了,但我想了解如何确定我的drawables缩放到什么尺寸的像素密度。
目前我的drawables位于我的drawable-hdpi文件夹中,而不是其他地方。我想知道如果我把它们放在一个通用的“drawable”文件夹中,我能将tile_height和tile_width引用为100x100吗?我已经阅读了获取内在高度和宽度的信息,但是当为视图或设备缩放位图时这无济于事。即使有可能以某种方式根据原始的可绘制尺寸引用图块大小,我认为应该有一种比通过任何特定数字引用它们更好的方法。在我的绘制方法中,我不应该能够找出缩放的大小吗?然后用它来确定绘制瓷砖的坐标是什么?更好的是,有没有办法在我将它绘制到画布之前强制我希望位图缩放到什么尺寸?
我已经在http://developer.android.com/guide/practices/screens_support.html读到像素密度,dpi,可绘制文件夹等,但是当我相对于彼此绘制图块并因此需要坐标时,这对我没有帮助。
我还研究了使用矩形绘制到画布,因为Canvas的drawbitmap()方法将Rectangle作为输入不依赖于像素密度。但是当我有一套12x6的瓷砖要绘制时,我不确定使用矩形是多么实用。我每个瓷砖位置需要一个矩形吗?
有关处理缩放位图的任何解释和/或更好的方法来绘制我正在绘制的内容将是最有帮助的。
答案 0 :(得分:1)
睡了一觉后回答了我自己的问题。要在android自动缩放后得到位图的高度,请在Bitmap上使用getWidth()和getHeight()。要强制位图缩放到特定大小,请使用scaleBitmap()