
写在前面
Python 语言结合 Pygame 库实现新年烟花秀的完整代码。
技术需求
- Pygame 库:用于创建图形界面、绘制图形、处理用户输入和管理时间。通过
pg.init()初始化,pg.display.set_mode()创建屏幕。 - 随机数生成:使用
random库控制烟花和粒子的颜色、速度、方向等,模拟自然效果。 - 物理模拟:利用
Vector2类表示坐标和速度,模拟重力和粒子运动轨迹。 - 粒子系统:烟花爆炸产生多个粒子对象,每个粒子拥有独立属性(颜色、大小、生命周期)。
- 路径追踪(Trail):记录粒子位置生成尾迹,模拟轨迹消失效果。
- 图形渲染:使用
pg.draw.circle()和screen.fill()绘制粒子与背景。 - 动态文本渲染:显示 "Happy New Year!" 文本。
- 事件处理:监听窗口关闭事件,控制程序运行状态。
- 面向对象编程:封装
Firework、Particle、Trail类以模块化设计。
完整代码
import pygame as pg
import random as ra
import math
pg.init()
pg.display.set_caption("🎇")
winScreen = pg.display.Info()
screenWidth = winScreen.current_w
screenHeight = winScreen.current_h
vector = pg.math.Vector2
trail_colors = [(45, 45, 45), (60, 60, 60), (75, 75, 75), (125, 125, 125), (150, 150, 150)]
# 痕迹类 (Trail)
class :
():
.index = index
.size = size
.dynamic = dynamic
.color = trail_colors[index] index < (trail_colors) (, , )
.alpha =
():
:
():
.firework = firework
.pos = vector(x, y)
.origin = vector(x, y)
.radius =
.remove =
.explosion_radius = ra.randint(, )
.life =
.acc = vector(, )
.trails = []
.prev_posx = [-] *
.prev_posy = [-] *
.firework:
.vel = vector(, -ra.randint(, ))
.size =
.colour = colour
i ():
.trails.append(Trail(i, .size, ))
:
.vel = vector(ra.uniform(-, ), ra.uniform(-, ))
.vel.x *= ra.randint(, .explosion_radius + )
.vel.y *= ra.randint(, .explosion_radius + )
.size = ra.randint(, )
.colour = ra.choice(colour)
i ():
.trails.append(Trail(i, .size, ))
():
.acc += force / .size
():
.vel += .acc
.pos += .vel
.acc = vector(, )
.life +=
.life > :
.remove =
():
pg.draw.circle(win, .colour, ((.pos.x), (.pos.y)), .size)
():
.remove
:
():
.colour = (ra.randint(, ), ra.randint(, ), ra.randint(, ))
.colours = (
(ra.randint(, ), ra.randint(, ), ra.randint(, )),
(ra.randint(, ), ra.randint(, ), ra.randint(, )),
(ra.randint(, ), ra.randint(, ), ra.randint(, ))
)
.firework = Particle(ra.randint(, screenWidth), screenHeight, , .colour)
.exploded =
.particles = []
.min_max_particles = vector(, )
():
g = vector(, ra.uniform(, ))
.exploded:
.firework.apply_force(g)
.firework.move()
tf .firework.trails:
tf.show(win)
.show(win)
.firework.vel.y >= :
.exploded =
.explode()
:
particle .particles:
particle.apply_force(vector(g.x + ra.uniform(-, ) / , g.y / + (ra.randint(, ) / )))
particle.move()
t particle.trails:
t.show(win)
particle.show(win)
():
amount = ra.randint((.min_max_particles.x), (.min_max_particles.y))
i (amount):
.particles.append(Particle(.firework.pos.x, .firework.pos.y, , .colours))
():
pg.draw.circle(win, .colour, ((.firework.pos.x), (.firework.pos.y)), .firework.size)
():
.exploded:
p .particles:
p.remove_check():
.particles.remove(p)
(.particles) == :
():
fw fireworks:
fw.update(screen)
fireworks[:] = [fw fw fireworks fw.remove()]
():
screen = pg.display.set_mode((screenWidth, screenHeight))
clock = pg.time.Clock()
running =
fireworks = []
font = pg.font.SysFont(, )
text = font.render(, , (, , ))
text_rect = text.get_rect(center=(screenWidth // , screenHeight // ))
running:
clock.tick()
event pg.event.get():
event. == pg.QUIT:
running =
screen.fill((, , ))
screen.blit(text, text_rect)
ra.randint(, ) == :
fireworks.append(Firework())
update(screen, fireworks)
pg.display.flip()
pg.quit()
__name__ == :
fire()





