Как преобразовать местоположение мыши в изометрической карте листов? - PullRequest
7 голосов
/ 02 августа 2011

Итак, мне удалось написать первую часть (алгоритм), чтобы вычислить позицию каждой плитки, где она должна быть расположена при рисовании этой карты (см. Ниже).Однако я должен быть в состоянии преобразовать местоположение мыши в соответствующую ячейку, и я почти выдернул свои волосы, потому что я не могу найти способ, как получить ячейку из местоположения мыши.Меня беспокоит то, что это требует довольно высокой математики или чего-то такого, чего я просто не могу заметить.
Например, если позиция мыши 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), выше приведен код, который я использую для преобразования ячейки.к позиции.Я перепробовал много вещей и вычислений для позиции в ячейку, но каждый из них потерпел неудачу.

Редактировать: После прочтения большого количества информации кажется , что используется за пределами экранакарта цветов (где цвета отображаются на плитках) - это самое быстрое и эффективное решение?

Ответы [ 6 ]

10 голосов
/ 30 декабря 2015

Я знаю, что это старый пост, но я хочу обновить его, поскольку некоторые люди все еще могут искать ответы на этот вопрос, как я делал это сегодня. Тем не менее, я понял это сам. Существует также гораздо лучший способ визуализации, чтобы избежать проблем с наложением плиток.

Код так же прост:

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_x и mouse_y - координаты экрана мыши.

tile_height и tile_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

7 голосов
/ 02 августа 2011
(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
4 голосов
/ 12 декабря 2012

enter image description here

Я рендерил плитки, как указано выше.

Решение очень простое!

первым делом:

Ширина и высота моей плитки равны = 32 это означает, что в изометрической проекции, ширина = 32 и высота = 16! Mapheight в этом случае 5 (макс. Значение Y)

y_iso & x_iso == 0, когда y_mouse = MapHeight / tilewidth / 2 и x_mouse = 0

когда x_mouse + = 1, y_iso - = 1

поэтому сначала я вычисляю "преобразование на пиксель"

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

TileX = x_mouse-TileY;

чтобы найти координаты плитки, я просто делю их на ширину плитки

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

СДЕЛАНО !! никогда не было проблем!

1 голос
/ 07 февраля 2012

Я нашел алгоритм на этом сайте 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));
0 голосов
/ 03 августа 2011

Хотя вы не упомянули об этом в своем первоначальном вопросе, в комментариях я думаю, что вы сказали, что программируете это во Flash. В этом случае Flash поставляется с функциями преобразования Matrix. Наиболее надежный способ преобразования между системами координат (например, в изометрические координаты) - это использование матричных преобразований:

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

Вы хотели бы повернуть и масштабировать матрицу в порядке, обратном тому, как вы поворачивали и масштабировали графику.

0 голосов
/ 02 августа 2011

Один из способов - повернуть его обратно в квадратную проекцию:

Сначала переведите 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);

Возможно, мне не хватает знака минус, но это общая идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...