Tôi đã có cùng một vấn đề cho một trò chơi mà tôi đang viết. Tôi tưởng tượng rằng vấn đề này sẽ khác nhau dựa trên cách bạn thực hiện chính xác hệ thống đẳng cự của mình, nhưng tôi sẽ giải thích cách tôi giải quyết vấn đề.
Lần đầu tiên tôi bắt đầu với chức năng brick_to_screen của mình. (Tôi giả sử đó là cách bạn đặt gạch ở vị trí phù hợp ở vị trí đầu tiên.) Hàm này có một phương trình để tính screen_x và screen_y. Của tôi trông như thế này (trăn):
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)
Tôi lấy hai phương trình đó và biến chúng thành một hệ phương trình tuyến tính. Giải hệ phương trình này trong bất kỳ phương pháp nào bạn chọn. (Tôi đã sử dụng phương pháp rref. Ngoài ra, một số máy tính vẽ đồ thị có thể giải quyết vấn đề này.)
Các phương trình cuối cùng trông như thế này:
# 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)
Như bạn có thể thấy, nó không đơn giản như phương trình ban đầu. Nhưng nó hoạt động độc đáo cho trò chơi tôi tạo ra. Cảm ơn lòng tốt cho đại số tuyến tính!
Cập nhật
Sau khi viết một lớp Point đơn giản với nhiều toán tử khác nhau, tôi đã đơn giản hóa câu trả lời này như sau:
# 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)