Yazdığım bir oyun için de aynı sorunu yaşadım. Bu sorunun sizi tam olarak izometrik sisteminizi nasıl uyguladığınıza bağlı olarak değişeceğini hayal ediyorum, ancak sorunu nasıl çözdüğümü açıklayacağım.
İlk olarak tile_to_screen işlevimle başladım. (Döşemeleri ilk etapta doğru konuma yerleştirdiğinizi varsayalım.) Bu fonksiyonun screen_x ve screen_y hesaplamak için bir denklemi vardır. Benimki şöyle görünüyordu (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)
Bu iki denklemi aldım ve onları doğrusal denklemler sistemi haline getirdim. Bu denklem sistemini seçtiğiniz herhangi bir yöntemle çözün. (Bir rref yöntemi kullandım. Ayrıca, bazı grafik hesap makineleri bu sorunu çözebilir.)
Son denklemler şöyle görünüyordu:
# 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)
Gördüğünüz gibi, ilk denklem gibi basit değil. Ama yarattığım oyun için iyi çalışıyor. Doğrusal cebir için çok şükür!
Güncelleme
Çeşitli operatörlerle basit bir Point sınıfı yazdıktan sonra, bu cevabı aşağıdakilere basitleştirdim:
# 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)