You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Pygame点击波浪扩散效果代码以提升运行效率?

优化Pygame波浪式方块扩散性能的方案

你的核心问题在于维护了所有已变红的方块列表,每次遍历整个列表检查邻接——随着扩散范围扩大,列表呈指数级增长,导致每次迭代的计算量和绘制量飙升。下面给出两种无需全局逐像素检查的高效实现方案,完全满足渐进式扩散、任意点击触发的需求:

方案一:分层BFS(广度优先搜索)

BFS天然适配波浪式扩散的特性,我们只需要维护当前扩散波前的方块层,而非所有已变红的方块。每次仅处理当前层的方块,将其邻接未变红的方块加入下一层,循环迭代即可实现平滑扩散。

代码示例

import pygame
import sys
from collections import deque

pygame.init()
SCREEN_SIZE = (800, 600)
CELL_SIZE = 10  # 单个方块的像素尺寸
GRID_WIDTH = SCREEN_SIZE[0] // CELL_SIZE
GRID_HEIGHT = SCREEN_SIZE[1] // CELL_SIZE
screen = pygame.display.set_mode(SCREEN_SIZE)
clock = pygame.time.Clock()

# 记录已访问的方块,避免重复处理
visited = [[False]*GRID_HEIGHT for _ in range(GRID_WIDTH)]
# 存储当前扩散层的网格坐标
current_layer = deque()

def start_diffusion(screen_x, screen_y):
    # 转换屏幕坐标为网格坐标
    grid_x = screen_x // CELL_SIZE
    grid_y = screen_y // CELL_SIZE
    if 0 <= grid_x < GRID_WIDTH and 0 <= grid_y < GRID_HEIGHT and not visited[grid_x][grid_y]:
        visited[grid_x][grid_y] = True
        current_layer.clear()
        current_layer.append((grid_x, grid_y))

running = True
while running:
    screen.fill((255,255,255))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            start_diffusion(*event.pos)
    
    # 处理当前扩散层,生成下一层
    next_layer = deque()
    for gx, gy in current_layer:
        # 绘制当前方块
        pygame.draw.rect(screen, (255,0,0), (gx*CELL_SIZE, gy*CELL_SIZE, CELL_SIZE, CELL_SIZE))
        # 检查四个方向的邻接方块
        for dx, dy in [(-1,0), (1,0), (0,-1), (0,1)]:
            nx, ny = gx + dx, gy + dy
            if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT and not visited[nx][ny]:
                visited[nx][ny] = True
                next_layer.append((nx, ny))
    # 更新为下一轮的扩散层
    current_layer = next_layer
    
    pygame.display.flip()
    clock.tick(30)

pygame.quit()
sys.exit()

优势

  • 每次仅处理当前波前的方块,计算量与扩散周长成正比,而非总面积
  • 内存占用极低,仅需存储当前层和下一层的坐标
  • 天然支持任意点击位置触发扩散,扩散逻辑平滑自然

方案二:距离场直接绘制环形波

如果追求极致性能,可以直接通过距离计算生成当前扩散半径对应的方块,无需维护任何已访问列表或队列。核心思路是:维护扩散中心和当前半径,每次仅绘制与中心距离等于当前半径的方块。

代码示例

import pygame
import sys

pygame.init()
SCREEN_SIZE = (800, 600)
CELL_SIZE = 10
GRID_WIDTH = SCREEN_SIZE[0] // CELL_SIZE
GRID_HEIGHT = SCREEN_SIZE[1] // CELL_SIZE
screen = pygame.display.set_mode(SCREEN_SIZE)
clock = pygame.time.Clock()

diffusion_center = None
current_radius = 0

def start_diffusion(screen_x, screen_y):
    global diffusion_center, current_radius
    diffusion_center = (screen_x // CELL_SIZE, screen_y // CELL_SIZE)
    current_radius = 0

running = True
while running:
    screen.fill((255,255,255))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            start_diffusion(*event.pos)
    
    if diffusion_center is not None:
        cx, cy = diffusion_center
        # 遍历当前半径覆盖的网格范围,仅绘制距离等于当前半径的方块
        for gx in range(max(0, cx - current_radius), min(GRID_WIDTH, cx + current_radius + 1)):
            for gy in range(max(0, cy - current_radius), min(GRID_HEIGHT, cy + current_radius + 1)):
                # 用棋盘距离(最大坐标差)模拟方块风格的波浪
                distance = max(abs(gx - cx), abs(gy - cy))
                if distance == current_radius:
                    pygame.draw.rect(screen, (255,0,0), (gx*CELL_SIZE, gy*CELL_SIZE, CELL_SIZE, CELL_SIZE))
        # 递增半径,直到超出屏幕范围
        if current_radius < max(GRID_WIDTH, GRID_HEIGHT):
            current_radius += 1
    
    pygame.display.flip()
    clock.tick(30)

pygame.quit()
sys.exit()

优势

  • 完全无需邻接检查或状态维护,性能最优
  • 代码逻辑简洁,易于调整扩散速度、波浪形状(比如改用欧氏距离实现圆形波浪)
  • 支持多点击触发多波扩散(只需维护多个中心和半径即可)

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:01:38