Ho avuto lo stesso problema per un gioco che stavo scrivendo. Immagino che questo problema differirà in base a come esattamente hai implementato il tuo sistema isometrico, ma ti spiego come ho risolto il problema.
Ho iniziato con la mia funzione tile_to_screen. (Suppongo sia il modo in cui stai posizionando le tessere nella posizione giusta in primo luogo.) Questa funzione ha un'equazione per calcolare screen_x e screen_y. Il mio sembrava così (python):
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)
Ho preso quelle due equazioni e le ho trasformate in un sistema di equazioni lineari. Risolvi questo sistema di equazioni con qualsiasi metodo tu scelga. (Ho usato un metodo rref. Inoltre, alcuni calcolatori grafici possono risolvere questo problema.)
Le equazioni finali sembravano così:
# 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)
Come puoi vedere, non è semplice come l'equazione iniziale. Ma funziona bene per il gioco che ho creato. Grazie al cielo per l'algebra lineare!
Aggiornare
Dopo aver scritto una semplice classe Point con vari operatori, ho semplificato questa risposta a quanto segue:
# 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)