У мене була така сама проблема для гри, яку я писав. Я думаю, що ця проблема буде відрізнятися залежно від того, як саме ви реалізували вашу ізометричну систему, але я поясню, як я вирішив проблему.
Я вперше розпочав свою функцію tile_to_screen. (Я припускаю, що саме так ви розміщуєте плитки в потрібному місці в першу чергу.) Ця функція має рівняння для обчислення screen_x та screen_y. Моя виглядала так (пітон):
def map_to_screen(self, point):
x = (SCREEN_WIDTH + (point.y - point.x) * TILE_WIDTH) / 2
y = (SCREEN_HEIGHT + (point.y + point.x) * TILE_HEIGHT) / 2
return (x, y)
Я взяв ці два рівняння і склав їх у систему лінійних рівнянь. Розв’яжіть цю систему рівнянь будь-яким обраним вами методом. (Я використовував метод rref. Також деякі графічні калькулятори можуть вирішити цю проблему.)
Кінцеві рівняння виглядали приблизно так:
# constants for quick calculating (only process once)
DOUBLED_TILE_AREA = 2 * TILE_HEIGHT * TILE_WIDTH
S2M_CONST_X = -SCREEN_HEIGHT * TILE_WIDTH + SCREEN_WIDTH * TILE_HEIGHT
S2M_CONST_Y = -SCREEN_HEIGHT * TILE_WIDTH - SCREEN_WIDTH * TILE_HEIGHT
def screen_to_map(self, point):
# the "+ TILE_HEIGHT/2" adjusts for the render offset since I
# anchor my sprites from the center of the tile
point = (point.x * TILE_HEIGHT, (point.y + TILE_HEIGHT/2) * TILE_WIDTH)
x = (2 * (point.y - point.x) + self.S2M_CONST_X) / self.DOUBLED_TILE_AREA
y = (2 * (point.x + point.y) + self.S2M_CONST_Y) / self.DOUBLED_TILE_AREA
return (x, y)
Як бачите, це не так просто, як початкове рівняння. Але це добре працює для створеної мною гри. Слава богу за лінійну алгебру!
Оновлення
Після написання простого класу Point з різними операторами я спростив цю відповідь на наступне:
# constants for quickly calculating screen_to_iso
TILE_AREA = TILE_HEIGHT * TILE_WIDTH
S2I_CONST_X = -SCREEN_CENTER.y * TILE_WIDTH + SCREEN_CENTER.x * TILE_HEIGHT
S2I_CONST_Y = -SCREEN_CENTER.y * TILE_WIDTH - SCREEN_CENTER.x * TILE_HEIGHT
def screen_to_iso(p):
''' Converts a screen point (px) into a level point (tile) '''
# the "y + TILE_HEIGHT/2" is because we anchor tiles by center, not bottom
p = Point(p.x * TILE_HEIGHT, (p.y + TILE_HEIGHT/2) * TILE_WIDTH)
return Point(int((p.y - p.x + S2I_CONST_X) / TILE_AREA),
int((p.y + p.x + S2I_CONST_Y) / TILE_AREA))
def iso_to_screen(p):
''' Converts a level point (tile) into a screen point (px) '''
return SCREEN_CENTER + Point((p.y - p.x) * TILE_WIDTH / 2,
(p.y + p.x) * TILE_HEIGHT / 2)