【发布时间】:2013-01-20 07:16:35
【问题描述】:
我正在开发一款使用 2D 瓷砖地图的游戏。地图是通过 SurfaceView 中的自定义方法 doDraw() 呈现的。这是一个简单的双循环,从二维数组中获取瓦片类型,确定该类型的相应位图,然后在指定坐标处将瓦片绘制到画布上。
以前我的可绘制文件夹中有占位符 .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 会有多实用。每个图块位置需要一个矩形吗?
任何关于处理缩放位图的解释和/或更好的方法来绘制我正在绘制的内容将是最有帮助的。
【问题讨论】:
标签: android canvas bitmap rendering