Войти
ПрограммированиеФорум2D графика и изометрия

Получение координат тайла шахматной карты

#0
5:14, 30 сен 2020

У меня есть вопрос, ответ на который я не получил, перерыв все англоязычные и русскоязычные форумы.

Заключается он в нахождении координат тайла по клику мыши в шахматной карте (staggered isometric grid).

my_staggered_map | Получение координат тайла шахматной карты

Концепция взята из источника https://www.gamedev.net/tutorials/_/technical/game-programming/is… -part-i-r747/, как один из вариантов решения задачи.

Основная суть поиска, насколько я понял, заключается в определении прямоугольников, которые пересекаются между собой в области клика:

Первый шаг: узнать, в какой области карты находится мышь.

rect | Получение координат тайла шахматной карты
# Возьмём рандомный клик х=450, y=257
TILE_WIDTH = 256
TILE_HEIGHT = 149
RegionX = x / TILE_WIDTH  # 1.76, int(RegionX) = 1
RegionY = (y / TILE_HEIGHT) * 2  # 3.32, int(RegionY) = 3

Выбранный прямоугольник находится в области [1, 3]


Второй шаг: узнать, где внутри прямоугольника находится наша мышь, найдя MouseMapX и MouseMapY

MouseMapX = x % TILE_WIDTH  # 194
MouseMapY = y % TILE_HEIGHT  # 98
map_x = MouseMapX / TILE_WIDTH  # 0.758 (тоже самое, только в процентах)
map_y = MouseMapY / TILE_HEIGHT  # 0.658

Третий шаг (проблема): определить точный тайл в (MouseMapX, MouseMapY).

Здесь без понятия как правильно вычислить принадлежность к 4 возможным сторонам прямоугольника

css | Получение координат тайла шахматной карты

Четвертый шаг: найти стороны (RegionDX и RegionDY) в следующей таблице.

tables | Получение координат тайла шахматной карты

Пятый шаг: используя RegionX, RegionY, RegionDX и RegionDY, найти TileX и TileY

TileX = RegionX + RegionDX
TileY = RegionY + RegionDY

Нужна любая помощь с вычислением тайла, на который был клик мышкой.. Для написания игры использую Python, Kivy и PyTmx

#1
11:27, 30 сен 2020

xXZyzzXx
> Третий шаг (проблема): определить точный тайл в (MouseMapX, MouseMapY).
>
> Здесь без понятия как правильно вычислить принадлежность к 4 возможным сторонам
> прямоугольника
Проценты \(y\) считаются снизу вверх или сверху вниз?
А, вроде понял, сверху вниз.

def subregion(px, py):
    if px - py < -0.5: return (-1, 1) # green
    elseif px - py > 0.5: return (0, -1) # yellow
    elseif px + py < 0.5: return (-1, -1) # red
    elseif px + py > 1.5: return (0, 1) # blue
    else: return (0, 0) # white
#2
11:44, 30 сен 2020

xXZyzzXx
А почему не KivEnt?

#3
12:05, 30 сен 2020

Знакомая схема.
На третьем шаге предполагался лайфхак :)
Вот мы определили

MouseMapX = x % TILE_WIDTH  # 194
MouseMapY = y % TILE_HEIGHT  # 98

По сути, это координаты внутри прямоугольника размерами TILE_WIDTHхTILE_HEIGHT (256х149).
Лайфхак состоит в том, что мы берем текстуру этого размера, раскрашенную так, как показано на картинке к третьему шагу, и выбираем из нее цвет пиксела по координатам (MouseMapX,MouseMapY). И потом, анализируя полученный цвет, окончательно находим TileX и TileY.

#4
15:35, 30 сен 2020

Delfigamer


Спасибо за ответ! Добавил в код, но у меня результаты неточные, поскольку я заметил одну оплошность в областях (помечены зелёным)

RegionX и RegionY

.

map | Получение координат тайла шахматной карты

А прямоугольник mouse map (отмечен красным) размером по ширине и высоте тайла, но не вписывается в размеры RegionX и RegionY.

По итогу не выходит правильно получить координаты. Как правильно узнать области?

#5
16:00, 30 сен 2020

Я бы попробовал вычислять две матрицы 3х3 - прямую и обратную. Прямую матрицу можно получить как комбинацию двухмерных аффинных преобразований: поворота на 45 градусов, переноса и масштабирования (или в другом порядке - точно не соображу сейчас), обратную - точно те же операции, но в обратном порядке и с обратным знаком. Далее прямая матрица умножается на вектор (x, y, 1.0f), где x и y - вещественные числа, целая часть - координаты клетки, дробная - координаты внутри клетки. Результат умножения - вектор (x', y', w), где x'/y и x'/w - экранные координаты. С обратной матрицей соответственно наоборот - преобразование экранных координат в мировые. Возможно это кажется оверхедом - на каждую точку по 9 умножений и 2 деления (или 11 умножений и 1 деление), но в итоге сам алгоритм достаточно очевиден, матрицы легко вычисляются в любой момент, кешируются целиком или частями (например матрицы поворота на 45 градусов хранятся все время как константы, матрицы масштабирования вычисляются на основе требуемого соотношения сторон и текущего масштаба, матрицы переноса вычисляются только при перемещениях виртуальной камеры).

#6
16:03, 30 сен 2020

Ptica

С картинкой получилось благодаря совету поиска пикселя, теперь только необходимо правильно определить регион

#7
16:07, 30 сен 2020

Nurik

Не знал о существовании, по идее можно будет перенести проект, если разница в синтаксисе небольшая.

#8
17:44, 30 сен 2020

xXZyzzXx

+ Показать
#9
23:09, 30 сен 2020

xXZyzzXx
> Спасибо за ответ! Добавил в код, но у меня результаты неточные, поскольку я
> заметил одну оплошность в областях (помечены зелёным)
Мне показалось, что RegionY должен идти на полную высоту ромба, а не наполовину - типа, если раскрасить ромбы как шахматную доску, то белые клетки - это все white-области из регионов, а чёрные клетки - они как раз на пересечении четырёх регионов, и составлены из red-yellow-green-blue, как раз по одной четвертинки с пересекающего региона.

#10
3:05, 1 окт 2020

Delfigamer

Да, прямоугольники совпали, успешно получилось найти нужный тайл!)

ывы | Получение координат тайла шахматной карты
def subregion(px, py, r_x, r_y):
    # print(f'{px - py:.3f}, {px + py:.3f}')
    r_x = int(r_x)
    r_y = int(r_y)
    foo = px - py
    bar = px + py
    if foo < 0 and bar > 1:  # Top
        return r_x, r_y
    elif foo < 0 and bar < 1:  # Left
        if py > 0.5:
            return r_x - 1, r_y + 1
        return r_x - 1, r_y
    elif foo > 0 and bar > 1:  # Right
        if py > 0.5:
            return r_x, r_y + 1
        return r_x, r_y
    elif foo > 0 and bar < 1:  # Bottom
        return r_x, r_y + 1

Вопрос закрыт, спасибо огромное.

#11
10:14, 1 окт 2020

xXZyzzXx
На всякий случай вот: https://gamedev.ru/code/forum/?id=123819&page=2&m=1751008#m18

#12
20:42, 1 окт 2020

Mikle
Если посмотреть внимательно, то можно обнаружить, что у ОПа не такая система координат, как в обычной изометрии.
Если показывать на примерах из того треда:
Изображение
То у ОПа система координат, как у гексов сверху посередине, только при s=0 и, соответственно, b=2h.

ПрограммированиеФорум2D графика и изометрия

Тема в архиве.