You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Pygame版青蛙过河克隆游戏性能卡顿问题排查求助

Fixing Car Sprite Stuttering in Your Procedural Frogger Clone

Hey there! Let's break down why your car sprites are stuttering and walk through actionable fixes—love that you're building this as a functional/procedural example for 11th graders, that's a great constraint to work within!

First, let's go through the most likely culprits and how to address them with your existing code:

1. Fix Floating-Point Coordinate Truncation

The biggest cause of stuttering here is probably how you're converting your car's floating-point position to integer screen coordinates. When you do car["x"] * TILE_SIZE, Pygame automatically truncates the decimal part (e.g., 38.9 becomes 38) instead of rounding it. This creates tiny jumps in the car's position every frame that add up to visible jitter.

Solution:

Round the coordinate values before passing them to blit to ensure smooth movement. Modify your car drawing code like this:

for car in state["cars"]:
    car_x = round(car["x"] * TILE_SIZE)
    car_y = round(car["y"] * TILE_SIZE)
    screen.blit(assets["car_sprite"], (car_x, car_y))

2. Pre-Render Your Background for Faster Drawing

Right now, you're redrawing every tile in the map every single frame. Even with 12x16 tiles, this adds up to 192 blit calls per frame—while not massive, it's unnecessary overhead that can contribute to frame drops and stuttering.

Solution:

Pre-render the entire background once at startup, then just blit that single surface each frame. Update your load_assets function to add a pre-rendered background:

def load_assets():
    # ... (keep existing code for loading tiles, frog, car)
    
    # Add this to pre-render the background
    background_surface = pygame.Surface(SCREEN_SIZE)
    background_surface.fill(BACKGROUND_COLOR)
    for row_idx, row in enumerate(map_data["map"]):
        for col_idx, tile_id in enumerate(row):
            tile_surface = tile_images.get(tile_id)
            if tile_surface:
                background_surface.blit(tile_surface, (col_idx * TILE_SIZE, row_idx * TILE_SIZE))
            else:
                pygame.draw.rect(background_surface, (255, 0, 255), (col_idx * TILE_SIZE, row_idx * TILE_SIZE, TILE_SIZE, TILE_SIZE))
    
    return {
        "tiles": tiles,
        "map_layout": map_data["map"],
        "frog": pygame.transform.scale(frog_img, (TILE_SIZE, TILE_SIZE)),
        "car_sprite": pygame.transform.scale(car_img, (TILE_SIZE, TILE_SIZE)),
        "background": background_surface  # Add the pre-rendered background
    }

Then update your draw_game function to use this pre-rendered surface instead of redrawing all tiles:

def draw_game(screen, assets, state):
    # 1. Blit the pre-rendered background (replaces fill + draw_background)
    screen.blit(assets["background"], (0, 0))
    
    # Draw all cars (with rounded coordinates as above)
    for car in state["cars"]:
        car_x = round(car["x"] * TILE_SIZE)
        car_y = round(car["y"] * TILE_SIZE)
        screen.blit(assets["car_sprite"], (car_x, car_y))
    
    # Draw frog
    frog_x, frog_y = state["frog_pos"]
    screen.blit(assets["frog"], (frog_x * TILE_SIZE, frog_y * TILE_SIZE))
    
    # Update display
    pygame.display.flip()

3. Fix Frame-Based Car Updates (Critical Bug!)

Looking at your update_game_state function: you're only updating cars when there's an event (like a key press or quit). That means if no events happen, the cars don't move for that frame! This is a major cause of stuttering.

Solution:

Move car updates outside the event loop so they run every single frame, regardless of input. Here's how to adjust your main loop:

def main():
    pygame.init()
    screen = pygame.display.set_mode(SCREEN_SIZE)
    pygame.display.set_caption("OpenFrogie")
    clock = pygame.time.Clock()
    assets = load_assets()
    state = get_initial_state()
    
    while state["is_running"]:
        dt = clock.tick(FPS) / 1000.0  # Convert milliseconds to seconds
        dt = min(dt, 0.05)  # Cap dt to prevent massive jumps if frame drops
        
        # Handle events first
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                state["is_running"] = False
            elif event.type == pygame.KEYDOWN:
                x, y = state["frog_pos"]
                if event.key == pygame.K_UP and y > 0:
                    state["frog_pos"] = (x, y - 1)
                elif event.key == pygame.K_DOWN and y < GRID_HEIGHT - 1:
                    state["frog_pos"] = (x, y + 1)
                elif event.key == pygame.K_LEFT and x > 0:
                    state["frog_pos"] = (x - 1, y)
                elif event.key == pygame.K_RIGHT and x < GRID_WIDTH - 1:
                    state["frog_pos"] = (x + 1, y)
        
        # Update cars EVERY frame, not just on events
        state["cars"] = update_cars(state["cars"], dt)
        
        draw_game(screen, assets, state)
    
    pygame.quit()
    sys.exit()

This separates event handling from state updates, ensuring cars move consistently every frame.

4. Additional Quick Checks

  • Ensure you're calling pygame.display.flip() (or update()) exactly once per frame—this is critical for smooth rendering.
  • Confirm your dt calculation uses seconds (not milliseconds) so car speed scales correctly with frame rate.

These changes should eliminate most, if not all, of the stuttering you're seeing. Start with fixing the frame-based car update and coordinate rounding first—those are the most impactful issues in your current code.

内容的提问来源于stack exchange,提问作者Nebri

火山引擎 最新活动