Pygame简易粒子系统随机无提示崩溃问题求助
PyGame粒子程序崩溃问题排查与修复
我是编程和粒子系统新手,跟着教程修改代码后遇到Bug:程序会无提示突然关闭,疑似和快速点击鼠标有关。相关代码如下:
import pygame, sys from random import randint pygame.init() screen = pygame.display.set_mode([500, 500]) clock = pygame.time.Clock() shrink_vel = -0.03 class Particles(): def __init__(self): self.particles = [] def emit(self): if self.particles: self.remove_particles() for particle in self.particles: particle[0][0] += particle[2][0] particle[0][1] += particle[2][1] particle[1] += shrink_vel pygame.draw.circle(screen, pygame.Color('White'), particle[0], int(particle[1])) def add_particles(self): pos_x, pos_y = pygame.mouse.get_pos() radius = 5 (direction_x, direction_y) = (randint(-3, 3), randint(-3, 3)) particle_circle = [[pos_x, pos_y], radius, (direction_x, direction_y)] self.particles.append(particle_circle) def remove_particles(self): particle_copy = [particle for particle in self.particles if particle[1] > 0] self.particles = particle_copy vel_spawn = 10 PARTICLE_EVENT = pygame.USEREVENT + 1 particle1 = Particles() while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: pygame.time.set_timer(PARTICLE_EVENT, vel_spawn) if event.type == pygame.MOUSEBUTTONUP: pygame.time.set_timer(PARTICLE_EVENT, 0) if event.type == PARTICLE_EVENT: particle1.add_particles() screen.fill((30, 30, 30)) particle1.emit() pygame.display.update() clock.tick(120)
问题原因
- 粒子半径绘制异常:当粒子半径
particle[1]衰减到0到1之间时,int(particle[1])会得到0,而PyGame的pygame.draw.circle不支持半径为0的参数,会触发未捕获的异常,直接导致程序崩溃。 - 快速点击加速触发:快速点击鼠标会短时间生成大量粒子,加速粒子进入0<半径<1的状态,集中触发上述错误。
- 定时器频繁切换隐患:快速点击时,
MOUSEBUTTONDOWN和MOUSEBUTTONUP事件频繁触发,反复开启/关闭定时器,可能导致事件队列异常,进一步加剧崩溃概率。
解决方法
1. 修复粒子半径绘制问题
两种可选方案:
- 提前移除小半径粒子:修改
remove_particles方法的过滤条件,在粒子半径小于等于1时就移除,避免出现0半径:def remove_particles(self): particle_copy = [particle for particle in self.particles if particle[1] > 1] self.particles = particle_copy - 强制最小绘制半径:绘制时确保半径至少为1,避免传入0:
pygame.draw.circle(screen, pygame.Color('White'), particle[0], max(1, int(particle[1])))
2. 优化定时器逻辑
新增状态变量,避免重复设置定时器,减少事件冲突:
# 在循环前添加状态变量 timer_active = False # 修改事件处理部分 if event.type == pygame.MOUSEBUTTONDOWN: if not timer_active: pygame.time.set_timer(PARTICLE_EVENT, vel_spawn) timer_active = True if event.type == pygame.MOUSEBUTTONUP: pygame.time.set_timer(PARTICLE_EVENT, 0) timer_active = False
完整修复代码
import pygame, sys from random import randint pygame.init() screen = pygame.display.set_mode([500, 500]) clock = pygame.time.Clock() shrink_vel = -0.03 class Particles(): def __init__(self): self.particles = [] def emit(self): if self.particles: self.remove_particles() for particle in self.particles: particle[0][0] += particle[2][0] particle[0][1] += particle[2][1] particle[1] += shrink_vel # 强制最小绘制半径为1 pygame.draw.circle(screen, pygame.Color('White'), particle[0], max(1, int(particle[1]))) def add_particles(self): pos_x, pos_y = pygame.mouse.get_pos() radius = 5 (direction_x, direction_y) = (randint(-3, 3), randint(-3, 3)) particle_circle = [[pos_x, pos_y], radius, (direction_x, direction_y)] self.particles.append(particle_circle) def remove_particles(self): # 半径小于等于1时移除粒子 particle_copy = [particle for particle in self.particles if particle[1] > 1] self.particles = particle_copy vel_spawn = 10 PARTICLE_EVENT = pygame.USEREVENT + 1 particle1 = Particles() timer_active = False while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: if not timer_active: pygame.time.set_timer(PARTICLE_EVENT, vel_spawn) timer_active = True if event.type == pygame.MOUSEBUTTONUP: pygame.time.set_timer(PARTICLE_EVENT, 0) timer_active = False if event.type == PARTICLE_EVENT: particle1.add_particles() screen.fill((30, 30, 30)) particle1.emit() pygame.display.update() clock.tick(120)
内容的提问来源于stack exchange,提问作者user18693808
相关产品推荐
相关产品推荐

