我在实现基于六边形网格的游戏时遇到问题。因为游戏需要一个 91 单元的六角板,就像我下面的简单板一样,我希望用户能够通过缩放/捏合来缩放板,并通过平移来移动它。但是,我的缩放和移动实现都不允许我同时拥有:
1) 一致的边界,让我能够将碎片拖放到构成每个单元格的 Drawable 上。
2)一致的相对定位,允许细胞在下面的相同配置中保持彼此相邻。
3) 平滑缩放和平移,让游戏快速运行,并拥有与其他应用类似的缩放/捏合体验。
我尝试过的一些事情(所有都使用 Activity -> SurfaceView -> Thread 完成,就像在 LunarLander 示例中一样):
绘制位图,用矩阵缩放位图,平移画布。处理点 2 和 3,但我不知道如何保持单元格的边界一致。HexCell 是一个包含单个单元格的 Drawable 的类,二维数组 board 包含 HexCells。
public void drawBoard(Canvas c, int posX, int posY, float scaleFactor, float pivotPointX, float pivotPointY, boolean firstDraw) { for(int i = 0; i < board.size(); i++) { for(int j = 0; j < board.get(i).size(); j++) { board.get(i).get(j).draw(bitmapCanvas); } } if(firstDraw) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); float scale; if(canvasWidth < canvasHeight) { scale = ((float) canvasWidth) / width; } else { scale = ((float) canvasHeight) / height; } Matrix matrix = new Matrix(); // Resize the bit map matrix.postScale(scale, scale); // Recreate the new Bitmap bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false); c.drawBitmap(bitmap, matrix, null); } c.save(); c.translate(posX, posY); Matrix matrix = new Matrix(); matrix.postScale(scaleFactor, scaleFactor, pivotPointX, pivotPointY); c.drawBitmap(bitmap, matrix, null); c.restore(); }
使用矩阵修改 Drawable 的边界。这更新了第 1 点的界限,通过一些调整,我想我可以得到 2 和 3,但我不确定如何使缩放停止“粘性”,这意味着不像第一种方法那样平滑。此外,当对单元格进行大量缩放时,其中一些单元格的大小会变得不同,并开始相对于其他单元格移出位置。
public void drawBoard(Canvas c, int posX, int posY, float scaleFactor, float pivotPointX, float pivotPointY, boolean firstDraw) { for(int i = 0; i < board.size(); i++) { for(int j = 0; j < board.get(i).size(); j++) { Rect bounds = board.get(i).get(j).getBounds(); RectF boundsF = new RectF(bounds.left, bounds.top, bounds.right, bounds.bottom); matrix.mapRect(boundsF); bounds = new Rect((int)boundsF.left, (int)boundsF.top, (int)boundsF.right, (int)boundsF.bottom); board.get(i).get(j).setBounds(bounds); board.get(i).get(j).draw(c); } } }
直接修改 Drawable 的边界。这会更新第 1 点的边界,但缺少第 2 点和第 3 点。此外,因为我没有使用带有 pivotPoints 的矩阵 postScale,所以单元格保持在它们所在的中心并且变得更小/更大而不会移动到每个单元旁边其他。
public void resize(int dx, int dy, float scaleFactor) { xPos += dx; yPos += dy; width *= scaleFactor; height *= scaleFactor; cell.setBounds(xPos, yPos, xPos + width, yPos + height); }
我应该怎么办?如何在缩放和移动时更新边界,以便最终将棋子放置在棋盘上?我是否应该放弃缩放和平移的愿望,而是使用 GridView 或类似的东西来实现板?
编辑:
对此进行了更多研究,我确定选项 1 是最好的方法。它速度更快,并使细胞保持一致的形成。我发现如果你反转应用于画布的转换并将其应用于触摸事件的坐标,你可以回到单元格的原始边界,因此适当地选择它们。
但是,我无法准确地反转转换。
x /= scaleFactor;
y /= scaleFactor;
x -= posX + pivotPointX;
y -= posY + pivotPointY;
不是以下的工作倒置:
canvas.save();
canvas.translate(posX, posY);
canvas.scale(scaleFactor, scaleFactor, pivotPointX, pivotPointY);
有谁知道如何适当地反转它?