如何将Pygame窗口坐标原点从左上角改为左下角及对应代码修改方案
Hey there! Let's tackle these two Pygame coordinate system questions—they're super common when you want to work with a Cartesian-style system where y increases upward instead of downward.
Question 1: How to move Pygame's (0,0) origin from the top-left to the bottom-left?
Pygame defaults to a top-left origin with y-values increasing downward. To switch to a bottom-left origin (y increasing upward), you’ve got two solid, practical approaches:
Option 1: Manual Coordinate Conversion (Great for Beginners)
This is the most straightforward method—you just adjust the y-coordinate of every element you draw based on the window height. Let’s say your window has a height of screen_height:
converted_y = screen_height - original_y
Important note: If you’re drawing elements with a height (like rectangles or sprites), you’ll need to subtract the element’s height too. Otherwise, the bottom of the element will align with the window’s bottom, instead of the element’s top matching your desired y-position. Example:
# Original rectangle (top-left origin): x=100, y=50, width=50, height=50 original_rect = pygame.Rect(100, 50, 50, 50) screen_height = win.get_height() # Convert to bottom-left origin: the rectangle's top sits at y=50 from the bottom converted_rect = pygame.Rect( original_rect.x, screen_height - original_rect.y - original_rect.height, original_rect.width, original_rect.height ) pygame.draw.rect(win, (255, 0, 0), converted_rect)
Option 2: Transform Matrices (Elegant for Complex Scenes)
For more advanced setups, use Pygame’s matrix transformation tools to flip the coordinate system entirely. This lets you draw directly using the bottom-left origin without manual conversions:
screen = pygame.display.set_mode((850, 600)) screen_height = screen.get_height() # Create a transformation matrix: flip the y-axis, then shift to fix the offset transform_matrix = pygame.math.Matrix44() transform_matrix.scale(1, -1) # Flip y-axis transform_matrix.translate(0, -screen_height) # Shift to align origin with bottom-left # Example: Draw a circle at (100, 50) in the new coordinate system new_point = pygame.math.Vector2(100, 50) converted_point = transform_matrix @ new_point pygame.draw.circle(screen, (0, 255, 0), (int(converted_point.x), int(converted_point.y)), 5)
Question 2: How to modify/extend win = pygame.display.set_mode((850, 600)) to switch the origin?
Let’s build out that initial window setup into a complete working example. Here are two actionable solutions:
Solution 1: Manual Conversion (Simple & Transparent)
This integrates the coordinate shift directly into your drawing loop:
import pygame pygame.init() # Initialize your window win = pygame.display.set_mode((850, 600)) win_height = win.get_height() clock = pygame.time.Clock() running = True while running: win.fill((255, 255, 255)) # White background # Handle events for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Draw using bottom-left origin coordinates # Example 1: Red rectangle at (100, 100) (100px right, 100px up from bottom) rect_x, rect_y = 100, 100 rect_w, rect_h = 50, 50 converted_rect_y = win_height - rect_y - rect_h pygame.draw.rect(win, (255, 0, 0), (rect_x, converted_rect_y, rect_w, rect_h)) # Example 2: Green circle centered at (200, 200) circle_x, circle_y = 200, 200 circle_radius = 20 converted_circle_y = win_height - circle_y # No need to subtract radius for center pygame.draw.circle(win, (0, 255, 0), (circle_x, converted_circle_y), circle_radius) pygame.display.flip() clock.tick(60) pygame.quit()
Solution 2: Surface Flipping (Draw First, Flip Later)
If you prefer to draw using Pygame’s default top-left coordinates and flip the whole screen afterward, this works too. Just draw everything to a temporary surface, then flip it vertically before blitting to the window:
import pygame pygame.init() # Initialize window and a temporary drawing surface win = pygame.display.set_mode((850, 600)) draw_surface = pygame.Surface(win.get_size()) clock = pygame.time.Clock() running = True while running: draw_surface.fill((255, 255, 255)) # Clear the drawing surface # Handle events for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Draw on the temporary surface (using default top-left coordinates) # This will end up looking like bottom-left origin after flipping pygame.draw.rect(draw_surface, (255, 0, 0), (100, 100, 50, 50)) pygame.draw.circle(draw_surface, (0, 255, 0), (200, 200), 20) # Flip the surface vertically and draw to the window flipped_surface = pygame.transform.flip(draw_surface, False, True) win.blit(flipped_surface, (0, 0)) # Don't forget to convert mouse input if you need it! mouse_x, mouse_y = pygame.mouse.get_pos() converted_mouse_y = win.get_height() - mouse_y # Use converted_mouse_y for any mouse-based logic pygame.display.flip() clock.tick(60) pygame.quit()
内容的提问来源于stack exchange,提问作者Dhruv

