我正在开发一款使用 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 会有多实用。每个图块位置需要一个矩形吗?
任何关于处理缩放位图和/或更好的方法来绘制我正在绘制的东西的解释都是最有帮助的。