Algorithm 如何在等距平铺贴图中变换鼠标位置?

Algorithm 如何在等距平铺贴图中变换鼠标位置?,algorithm,math,Algorithm,Math,因此,我自己编写了第一部分(算法),以计算绘制此地图时每个瓷砖的位置(请参见下文)。然而,我需要能够将鼠标位置转换为适当的单元格,我几乎已经脱发了,因为我不知道如何从鼠标位置获取单元格。我担心的是,这涉及到一些相当高的数学水平,或者一些我无法注意到的简单问题。 例如,如果鼠标位置112;35我如何计算/转换它以得到单元格为2;3在那个位置? 也许这里有一些数学思维很好的程序员会在这方面帮助我,或者有人知道怎么做,或者可以提供一些信息 var cord:Point = new Point(); c

因此,我自己编写了第一部分(算法),以计算绘制此地图时每个瓷砖的位置(请参见下文)。然而,我需要能够将鼠标位置转换为适当的单元格,我几乎已经脱发了,因为我不知道如何从鼠标位置获取单元格。我担心的是,这涉及到一些相当高的数学水平,或者一些我无法注意到的简单问题。
例如,如果鼠标位置112;35我如何计算/转换它以得到单元格为2;3在那个位置? 也许这里有一些数学思维很好的程序员会在这方面帮助我,或者有人知道怎么做,或者可以提供一些信息

var cord:Point = new Point();
cord.x = (x - 1) * 28 + (y - 1) * 28;
cord.y = (y - 1) * 14 + (x - 1) * (- 14);

说到贴图,每个单元格(透明平铺56x28像素)都位于前一个单元格的中心(或单元格1;1的零位置),上面是我用于将单元格转换为位置的代码。我尝试了很多东西和计算位置到细胞,但每一个都失败了

编辑: 在阅读了大量信息后,使用屏幕外颜色映射(颜色映射到瓷砖)似乎是最快和最有效的解决方案

(1) x` = 28x -28 + 28y -28  = 28x + 28y -56
(2) y` = -14x +14 +14y -14 = -14x + 14y
转换表:

[x] [28  28 -56 ] = [x`]
[y] [-14 14  0  ]   [y`]
[1] [0    0  1  ]   [1 ]

[28  28 -56 ] ^ -1 
[-14 14  0  ]
[0    0  1  ] 
用绘图仪计算(我喜欢


一种方法是将其旋转回方形投影:

首先平移y,使尺寸相对于原点:

 x0 = x_mouse;
 y0 = y_mouse-14
然后按瓷砖大小进行缩放:

 x1 = x/28;   //or maybe 56?
 y1 = y/28
然后按投影角度旋转

 a = atan(2/1);   
 x_tile = x1 * cos(a) - y1 * sin(a);
 y_tile = y1 * cos(a) + x1 * sin(a);

我可能漏掉了一个减号,但这是大意。

虽然你在最初的问题中没有提到,但在评论中,我想你说你正在用Flash编程。在这种情况下,Flash带有矩阵变换功能。在坐标系之间进行转换(例如转换为等轴测坐标)的最可靠方法是使用矩阵变换:


您可能希望以与图形旋转和缩放相反的方式旋转和缩放矩阵。

我在这个网站上找到了算法。我无法让它为我正常工作,但我通过尝试和错误将其更改为这种形式,现在它为我工作

int x = mouse.x + offset.x - tile[0;0].x; //tile[0;0].x is the value of x form witch map was drawn
int y = mouse.y + offset.y;
double _x =((2 * y + x) / 2);
double _y= ((2 * y - x) / 2);
double tileX = Math.round(_x / (tile.height - 1)) - 1;
double tileY = Math.round(_y / (tile.height - 1));
这是我的地图生成

for(int x=0;x<max_X;x++)
for(int y=0;y<max_Y;y++)
map.drawImage(image, ((max_X - 1) * tile.width / 2) - ((tile.width - 1) / 2 * (y - x)), ((tile.height - 1) / 2) * (y + x));
for(int x=0;x

我像上面那样渲染瓷砖

解决方法很简单

第一件事:

[1/56 -1/28  1 ]
[1/56  1/28  1 ]
[0      0    1 ]

x = 1/56*x` - 1/28y` + 1
y = 1/56*x` + 1/28y` + 1
我的瓷砖宽度和高度均为=32 这意味着在等轴测视图中, 宽度=32,高度=16! 本例中的贴图高度为5(最大Y值)

当y_鼠标=MapHeight/tilewidth/2且x_鼠标=0时,y_iso&x_iso==0

当x_鼠标+=1时,y_iso-=1

首先我计算“每像素变换”

TileY=((y_鼠标*2)-(贴图高度*tilewidth)/2)+x_鼠标)/2

TileX=x_鼠标-TileY

要找到平铺坐标,我只需按平铺宽度将两者都划分

TileY=TileY/32; TileX=TileX/32

完成!!
从来没有遇到过任何问题!

我知道这是一篇老文章,但我想更新它,因为有些人可能仍然在寻找这个问题的答案,就像我今天早些时候一样。不过,我自己发现了这一点。还有一种更好的方法来渲染它,这样你就不会遇到重叠问题

代码如下所示:

mouse_grid_x = floor((mouse_y / tile_height) + (mouse_x / tile_width));
mouse_grid_y = floor((-mouse_x / tile_width) + (mouse_y / tile_height));
鼠标x
鼠标y
是鼠标屏幕坐标

tile\u height
tile\u width
是实际的tile大小,而不是图像本身。正如我在示例图片中看到的,我在我的tile下添加了污垢,这只是为了更容易渲染,实际大小是24 x 12。坐标也是“地板”的,以保持结果网格x和y向下舍入

还请注意,我使用/2(红点)从y=0和x=tile_渲染这些瓷砖。这意味着我的0,0实际上从瓷砖的上角(倾斜)开始,而不是在户外。将这些瓷砖视为旋转的正方形,您仍然希望从0,0像素开始

将从Y=0和X=0开始渲染平铺,以映射大小。渲染第一行后,您将向下和向左跳过几个像素。这将使下一行平铺与第一行重叠,这是保持层正确重叠的好方法。您应该渲染平铺,然后在移动到下一行之前在该平铺上渲染任何内容下一个

我还将添加一个渲染示例:

for (yy = 0; yy < map_height; yy++)
{
     for (xx = 0; xx < map_width; xx++)
     {
          draw tiles here with tile coordinates:
          tile_x = (xx * 12) - (yy * 12) - (tile_width / 2)
          tile_y = (yy * 6) + (xx * 6)

          also draw whatever is on this tile here before moving on
     }
}
for(yy=0;yy

你用什么来画图?许多图形框架(如OpenGL)都有辅助方法来为你进行鼠标到世界的转换。请参见Q:…基本上,如果你知道转换的一面,那么很容易得到另一面。因此,你有V*A=V`…两边都乘以A(-1),得到V*1=V`*A(-1)我正在变换的是什么?整个地图图像以矩形为基础,然后很容易计算单元格?有没有一种方法可以在不旋转地图图像的情况下用数学计算鼠标在单元格中的位置?@Yochai Timmer很好的解决方案。这不只是一种仿射变换吗?这种变换会是像素级的吗?效率有多高将在每次鼠标移动时都进行这些变换?旋转整个地图图像是吗?使其基于矩形?您实际上不必旋转整个地图。只需将旋转应用于鼠标位置,就可以得到坐标中的等效位置,就像地图已经旋转一样。然而,我认为@yochai的答案是一个更实用的解决方案。在@yochai的示例中,它是否也只对鼠标位置应用旋转?或者不应用?因为我不知道如何倾斜或旋转鼠标位置,例如,(112,35)。比