如何实现图片随机显示隐藏?PyGame打地鼠功能故障求助
Hey there! Let's get to the bottom of why your mole won't disappear and why time.delay(10) is crashing your program. The root of the problem is that you're blocking Pygame's event loop—a big no-no for any interactive Pygame app.
Why time.delay(10) Breaks Everything
When you call time.delay(10), it freezes your entire program for 10 seconds. During that time, Pygame can't process window events (like closing the window), update the screen, or do anything else. Your operating system will see this as an unresponsive program and either force-close it or throw an error—exactly what you're seeing.
The Pygame-Friendly Way to Handle Timing
Instead of blocking the loop, we'll use Pygame's built-in time tools to track when to switch moles without freezing the program. Here's a step-by-step fix with example code:
Example Fixed Code
import pygame import random # Initialize Pygame pygame.init() # Screen setup screen_width, screen_height = 800, 600 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("Whack-a-Mole") # Load mole images (replace with your file paths) mole_images = [ pygame.image.load("mole1.png").convert_alpha(), pygame.image.load("mole2.png").convert_alpha() ] # Resize images if needed mole_images = [pygame.transform.scale(img, (100, 100)) for img in mole_images] # Mole state variables current_mole_idx = random.randint(0, len(mole_images)-1) mole_pos = (random.randint(50, screen_width-150), random.randint(50, screen_height-150)) display_duration = 10000 # 10 seconds in milliseconds start_time = pygame.time.get_ticks() # Get current time when mole appears clock = pygame.time.Clock() running = True while running: # Handle events first—critical for preventing crashes for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Check if it's time to switch moles current_time = pygame.time.get_ticks() if current_time - start_time >= display_duration: # Pick a new random mole and position current_mole_idx = random.randint(0, len(mole_images)-1) mole_pos = (random.randint(50, screen_width-150), random.randint(50, screen_height-150)) start_time = current_time # Reset the timer # Redraw everything screen.fill((0, 128, 0)) # Green background screen.blit(mole_images[current_mole_idx], mole_pos) pygame.display.flip() # Control frame rate (keeps loop smooth) clock.tick(60) pygame.quit()
Key Changes Explained
- Use
pygame.time.get_ticks(): This returns the number of milliseconds since Pygame initialized, so we can calculate how long the current mole has been displayed without blocking the loop. - Event Loop Priority: We always process events first (like the quit event) to keep the program responsive to user actions.
- Frame Rate Control:
clock.tick(60)ensures the loop runs at ~60 FPS, keeping the screen updated smoothly without wasting resources. - Non-Blocking Timing: Instead of freezing the program, we just check the time difference each loop iteration and switch moles when the 10-second mark hits.
Alternative: Custom Pygame Events
If you prefer event-driven logic, you can create a custom event that triggers every 10 seconds to switch moles:
# Add this after initializing Pygame SWITCH_MOLE = pygame.USEREVENT + 1 pygame.time.set_timer(SWITCH_MOLE, display_duration) # Trigger every 10s # Then in the event loop: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == SWITCH_MOLE: # Switch mole logic here current_mole_idx = random.randint(0, len(mole_images)-1) mole_pos = (random.randint(50, screen_width-150), random.randint(50, screen_height-150))
This approach is great if you want to separate timing logic from the main loop flow.
Final Tips
- Never use
time.sleep()ortime.delay()in Pygame's main loop—they block the event loop. - Always redraw the entire screen each loop iteration (fill the background first!) to make sure old sprites disappear when they're supposed to.
内容的提问来源于stack exchange,提问作者Christo Hardmn

