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

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)

问题原因

  1. 粒子半径绘制异常:当粒子半径particle[1]衰减到0到1之间时,int(particle[1])会得到0,而PyGame的pygame.draw.circle不支持半径为0的参数,会触发未捕获的异常,直接导致程序崩溃。
  2. 快速点击加速触发:快速点击鼠标会短时间生成大量粒子,加速粒子进入0<半径<1的状态,集中触发上述错误。
  3. 定时器频繁切换隐患:快速点击时,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:45:35