Pygame开发闪避游戏遇碰撞误判与小行星水平移动失效问题
Hey there! Let's work through those two bugs in your Pygame dodge game—they're easy fixes once you spot the root causes.
Your collision issue stems from two key mistakes:
- Outdated
player_rect: You initializeplayer_rectat the start ofgameLoop(), but never update it when the player moves with arrow keys. The collision check uses the original player position instead of where they actually are on screen. - Uncleared
objectslist: You keep appending asteroid rects toobjectsevery frame without clearing it, so the list fills up with old, stale rects from previous frames—leading to false collision triggers.
Here's how to fix it:
- Update
player_rectto match the player's current position right before collision checks. - Recreate the
objectslist each frame to only include the latest asteroid positions.
Modified collision and drawing code snippet:
# -------------------- Event Handling -------------------- while True: # Keep your existing event/keyboard handling code here # Update asteroid positions (we'll fix this next) for i in range(len(random_x_pos)): random_x_pos[i] += object_x_vel[i] random_y_pos[i] += object_y_vel[i] # -------------------- COLLISION -------------------- # Create a fresh player rect for the current position player_rect = pygame.Rect(x_pos, y_pos, player_dim, player_dim) # Rebuild objects list with current asteroid rects objects = [] for i in range(amount_of_objects): obj_rect = pygame.Rect(random_x_pos[i], random_y_pos[i], object_dimensions, object_dimensions) objects.append(obj_rect) collision = player_rect.collidelist(objects) if collision != -1: lives -= 1 if lives >= 0: gameLoop() else: pygame.quit() quit() # -------------------- DRAWING -------------------- gameDisplay.fill(black) # Redraw player with the updated rect pygame.draw.rect(gameDisplay, pink, player_rect) # Redraw asteroids using the same rects we checked for collisions for obj_rect in objects: pygame.draw.rect(gameDisplay, white, obj_rect) pygame.display.update() clock.tick(FPS)
The problem here is that looping for x in random_x_pos modifies a copy of the list element—not the actual value stored in random_x_pos. Plus, using random_x_pos.index(x) can cause bugs if multiple asteroids share the same x-position (it always returns the first occurrence's index).
Instead, loop using indexes to directly modify the list values:
# Replace your old asteroid position update loop with this: for i in range(len(random_x_pos)): random_x_pos[i] += object_x_vel[i] random_y_pos[i] += object_y_vel[i]
This way, you're directly updating the x and y positions stored in your lists, so asteroids will move both horizontally and vertically as intended.
- When restarting
gameLoop()after a collision, consider resetting asteroid positions (right now, they keep their positions from the previous run). Moving asteroid initialization to a separate function makes this easy to call on game start and after life loss. - Using
pygame.Rectexplicitly (instead of relying on the return value ofpygame.draw.rect()) makes position and collision management cleaner—drawing functions return rects, but creating them explicitly for logic avoids confusion.
内容的提问来源于stack exchange,提问作者PlayerOne

