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

时间:2011-08-02 16:46:12

标签: algorithm math

所以我自己编写了第一部分(算法)来计算每个瓷砖在绘制此贴图时应该放置的位置(参见下面的内容)。然而,我需要能够将鼠标位置转换为适当的单元格,我几乎已经脱掉了我的头发,因为我无法弄清楚如何从鼠标位置获取单元格。我担心的是它涉及一些非常高的数学或者我只是容易的东西,我无法注意到 例如,如果鼠标位置 112; 35 ,我如何计算/转换它以使该单元格 2; 3 ? 也许这里有一些非常优秀的数学思维程序员可以帮助我,或者知道如何做或者可以提供一些信息的人?

enter image description here

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

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

修改 在阅读了很多信息之后似乎使用屏幕外的颜色图(颜色映射到图块)是最快最有效的解决方案吗?

6 个答案:

答案 0 :(得分:10)

我知道这是一篇很老的帖子,但我想更新一下,因为有些人可能仍然在寻找这个问题的答案,就像我今天早些时候一样。但是,我自己想出来了。还有一种更好的方式来渲染它,这样你就不会出现瓦片重叠的问题。

代码就像这样简单:

mouse_grid_x = floor((mouse_y / tile_height) + (mouse_x / tile_width));
mouse_grid_y = floor((-mouse_x / tile_width) + (mouse_y / tile_height));

mouse_xmouse_y是鼠标屏幕坐标。

tile_heighttile_width是实际的图块大小,而不是图像本身。正如你在我的示例图片上看到的那样,我在瓷砖下面添加了污垢,这只是为了更容易渲染,实际尺寸是24 x 12.坐标也是"地板"保持结果网格x和y向下舍入。

另请注意,我从y = 0和x = tile_with / 2(红点)渲染这些图块。这意味着我的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
     }
}

Isometric Image

答案 1 :(得分:7)

(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  ] 

使用绘图仪计算(我喜欢 wims

[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

答案 2 :(得分:4)

enter image description here

我像上面一样渲染了瓷砖。

溶剂非常简单!

第一件事:

我的瓷砖宽度和高度都是= 32 这意味着在等轴测视图中, 宽度= 32,高度= 16! 在这种情况下,Mapheight是5(最大Y值)

y_iso&amp;当y_mouse = MapHeight / tilewidth / 2和x_mouse = 0时,x_iso == 0

当x_mouse + = 1时,y_iso - = 1

所以首先我计算“每像素转换”

TileY =((y_mouse * 2) - ((MapHeight * tilewidth)/ 2)+ x_mouse)/ 2;

TileX = x_mouse-TileY;

找到瓷砖坐标我只是通过tilewidth

来划分

TileY = TileY / 32; TileX = TileX / 32;

DONE !! 没有任何问题!

答案 3 :(得分:1)

我在这个网站http://www.tonypa.pri.ee/tbw/tut18.html找到了算法。我无法让它适当地为我工作,但我通过反复试验将其更改为此表格,现在它对我有效。

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));

答案 4 :(得分:0)

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

首先翻译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);

我可能错过了一个减号,但这是一般的想法。

答案 5 :(得分:0)

虽然你在原始问题中没有提到它,但在评论中我认为你说你在Flash中编程。在这种情况下,Flash附带了Matrix转换功能。在坐标系之间转换的最稳健的方法(例如等距坐标)是使用矩阵变换:

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html

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