ฉันมีปัญหาเดียวกันนี้สำหรับเกมที่ฉันกำลังเขียน ฉันคิดว่าปัญหานี้จะแตกต่างกันไปตามวิธีการที่คุณนำระบบ isometric ของคุณไปใช้จริง แต่ฉันจะอธิบายว่าฉันแก้ปัญหาได้อย่างไร
ฉันเริ่มแรกด้วยฟังก์ชั่น 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)
อย่างที่คุณเห็นมันไม่ง่ายเหมือนสมการเริ่มต้น แต่มันทำงานได้ดีสำหรับเกมที่ฉันสร้างขึ้น ขอบคุณพระเจ้าสำหรับพีชคณิตเชิงเส้น!
ปรับปรุง
หลังจากเขียนคลาสพอยต์ง่าย ๆ กับโอเปอเรเตอร์ที่หลากหลายฉันทำให้คำตอบนี้ง่ายขึ้น:
# 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)