每一行都添加了中文注释,方便少儿们阅读中文一样理解程序;
少儿们也可以自行修改本程序,实现不同的烟花效果;
比如下面的代码是控制烟花爆竹后的半径大小
修改上面的数字会影响下图的烟花大小
阅读下面的代码就可以增加烟花的数量,只要少儿们可以像阅读文章一样看代码,就可以适当的理解本程序
音乐和图片有兴趣的可以私聊,因为每个人的电脑不一样,即使吧图和因为提供后,还需要放到对应的项目中,所以需要适当的指导少儿们;
主程序
# 导入数学库
import math
# 导入随机库的 uniform, randint, choice函数
from random import uniform, randint, choice
# 导入pygame库
import pygame
# 定义一个二维向量
vector = pygame.math.Vector2
# 定义重力向量 ,正数向上,负数向下,
# 可以自行修改参数,查看烟花效果
gravity = vector(0, 0.3)
# 控制窗口的大小 ,宽=高= 800,创建了一个800*800像素的窗口
# 可以自行更改参数,改变窗口大小
DISPLAY_WIDTH = DISPLAY_HEIGHT = 800
# 定义烟花轨迹的颜色
# 可以自行更改颜色参数,改变颜色
trail_colours = [(45, 45, 45), (60, 60, 60), (75, 75, 75), (125, 125, 125), (150, 150, 150)]
# 定义动态偏移量
# 可以自行修改参数,查看烟花效果
dynamic_offset = 1
# 定义静态偏移量
# 可以自行修改参数,查看烟花效果
static_offset = 3
# 定义烟花类
class Firework:
# 初始化类方法
def __init__(self):
# 随机生成烟花的颜色
self.colour = (randint(0, 255), randint(0, 255), randint(0, 255))
# 颜色是4中,可以自己追加代码,改变成更多的颜色
self.colours = (
# 这行代码去掉注释就是5中颜色,加入这样多多行就可以实现更多颜色
# (randint(0, 255), randint(0, 255), randint(0, 255)),
(randint(0, 255), randint(0, 255), randint(0, 255)),
(randint(0, 255), randint(0, 255), randint(0, 255)),
(randint(0, 255), randint(0, 255), randint(0, 255)),
(randint(0, 255), randint(0, 255), randint(0, 255)))
# 创建烟花粒子
# 可以自行修改参数,查看烟花效果
self.firework = Particle(randint(0, DISPLAY_WIDTH), DISPLAY_HEIGHT, True,
self.colour)
# 初始化烟花爆炸状态为未爆炸
self.exploded = False
# 初始化烟花粒子列表为空
self.particles = []
# 定义烟花粒子的最小和最大数量
# 可以自行修改,查看烟花效果
self.min_max_particles = vector(100, 225)
# 定义更新烟花状态的方法
def update(self, win):
# 如果烟花未爆炸
if not self.exploded:
# 对烟花施加重力
self.firework.apply_force(gravity)
# 移动烟花
self.firework.move()
# 遍历烟花的轨迹
for tf in self.firework.trails:
# 显示烟花的轨迹
tf.show(win)
# 显示烟花
self.show(win)
# 如果烟花的垂直速度大于等于0
if self.firework.vel.y >= 0:
# 设置烟花的爆炸状态为已爆炸
self.exploded = True
# 爆炸烟花
self.explode()
# 如果烟花已爆炸
else:
# 遍历烟花粒子
for particle in self.particles:
# 对烟花粒子施加力
particle.apply_force(vector(gravity.x + uniform(-1, 1) / 20, gravity.y / 2 + (randint(1, 8) / 100)))
# 移动烟花粒子
particle.move()
# 遍历烟花粒子的轨迹
for t in particle.trails:
# 显示烟花粒子的轨迹
t.show(win)
# 显示烟花粒子
particle.show(win)
# 定义烟花爆炸的方法
def explode(self):
# amount 数量
# 随机生成烟花粒子的数量
amount = randint(self.min_max_particles.x, self.min_max_particles.y)
# 遍历烟花粒子的数量
for i in range(amount):
# 创建烟花粒子并添加到烟花粒子列表
self.particles.append(Particle(self.firework.pos.x, self.firework.pos.y, False, self.colours))
# 定义显示烟花的方法
def show(self, win):
# 在窗口上绘制烟花
pygame.draw.circle(win, self.colour, (int(self.firework.pos.x), int(self.firework.pos.y)), self.firework.size)
# 其他爆炸代码
self.show_text()
# 定义显示文本
def show_text(self):
# 创建字体对象
# None表示使用默认字体,36是字体大小
font = pygame.font.Font(None, 66)
# 创建文本对象
text = font.render('2024 New Year', True,(55, 255, 255))
# 获取文本对象的矩形
text_rect = text.get_rect()
# 设置文本对象的位置
# text_rect.center = (int(self.firework.pos.x), int(self.firework.pos.y))
# 将文本对象放在窗口的中心
text_rect.center = (400, 400)
win.blit(text, text_rect) # 在屏幕上显示文本
# 定义移除烟花的方法
def remove(self):
# 如果烟花已爆炸
if self.exploded:
# 遍历烟花粒子
for p in self.particles:
# 如果烟花粒子的移除状态为True
if p.remove is True:
# 移除烟花粒子
self.particles.remove(p)
# 如果烟花粒子列表为空
if len(self.particles) == 0:
# 返回True
return True
# 如果烟花粒子列表不为空
else:
# 返回False
return False
# 定义烟花粒子(包含轨迹)类
class Particle:
#初始化类
def __init__(self, x, y, firework, colour):
# 定义烟花
self.firework = firework
# 粒子位置
self.pos = vector(x, y)
# 粒子起始位置
self.origin = vector(x, y)
# 粒子半径 这个需要跟爆炸半径 一起修改,比如这个修改50,爆炸半径一定要在50内
self.radius = 20
# 是否移除粒子
self.remove = False
# 爆炸半径,这个不能超过radius编列,粒子半径
self.explosion_radius = randint(5, 18)
# 粒子生命周期
# 可自行修改,查看烟花效果
self.life = 0
# 粒子加速度
# 可自行修改,查看烟花效果
self.acc = vector(0, 0)
# trail variables
# 存储粒子轨迹对象
self.trails = []
# 存储最近10个x位置
# 可自行修改,查看烟花效果
self.prev_posx = [-10] * 10
# 存储最近10个y位置
# 可自行修改,查看烟花效果
self.prev_posy = [-10] * 10
# 如果是烟花
if self.firework:
# 设置速度
self.vel = vector(0, -randint(17, 20))
# 设置大小
self.size = 5
# 设置颜色
self.colour = colour
# 创建5个轨迹
for i in range(5):
self.trails.append(Trail(i, self.size, True))
# 如果不是烟花
else:
# 设置速度
self.vel = vector(uniform(-1, 1), uniform(-1, 1))
# 设置x方向速度
self.vel.x *= randint(7, self.explosion_radius + 2)
# 设置y方向速度
self.vel.y *= randint(7, self.explosion_radius + 2)
# 设置大小
# 可自行修改,查看烟花效果
self.size = randint(2, 4)
# 设置颜色
self.colour = choice(colour)
# 5 个 tails总计
# 创建5个轨迹
for i in range(5):
self.trails.append(Trail(i, self.size, False))
# 应用力
def apply_force(self, force):
self.acc += force
# 移动粒子
def move(self):
# 如果不是烟花
if not self.firework:
# 减小x方向速度
self.vel.x *= 0.8
# 减小y方向速度
self.vel.y *= 0.8
# 更新速度
self.vel += self.acc
# 更新位置
self.pos += self.vel
# 重置加速度
self.acc *= 0
# 检查粒子的爆炸范围
if self.life == 0 and not self.firework:
distance = math.sqrt((self.pos.x - self.origin.x) ** 2 + (self.pos.y - self.origin.y) ** 2)
if distance > self.explosion_radius:
self.remove = True
# 粒子衰减
self.decay()
# 更新轨迹
self.trail_update()
# 更新生命周期
self.life += 1
# 显示粒子
def show(self, win):
pygame.draw.circle(win, (self.colour[0], self.colour[1], self.colour[2], 0), (int(self.pos.x), int(self.pos.y)),
self.size)
# 粒子衰减
def decay(self):
# 在早期阶段有小概率衰减
if 50 > self.life > 10:
ran = randint(0, 30)
if ran == 0:
self.remove = True
# 在后期阶段有较大概率衰减
elif self.life > 50:
ran = randint(0, 5)
if ran == 0:
self.remove = True
# 更新轨迹
def trail_update(self):
# 移除最旧的x位置
self.prev_posx.pop()
# 添加最新的x位置
self.prev_posx.insert(0, int(self.pos.x))
# 移除最旧的y位置
self.prev_posy.pop()
# 添加最新的y位置
self.prev_posy.insert(0, int(self.pos.y))
# 更新每个轨迹的位置
for n, t in enumerate(self.trails):
if t.dynamic:
t.get_pos(self.prev_posx[n + dynamic_offset], self.prev_posy[n + dynamic_offset])
else:
t.get_pos(self.prev_posx[n + static_offset], self.prev_posy[n + static_offset])
# Trail:烟花轨迹,本质上是一个点 。
# 创建 Trail 类,定义 show 方法绘制轨迹 、get_pos 实时获取轨迹坐标
class Trail:
def __init__(self, n, size, dynamic):
# 在轨迹中的位置
self.pos_in_line = n
# 轨迹位置
self.pos = vector(-10, -10)
# 是否动态
self.dynamic = dynamic
# 如果是动态轨迹
if self.dynamic:
# 设置颜色
self.colour = trail_colours[n]
# 设置大小
self.size = int(size - n / 2)
# 如果不是动态轨迹
else:
# 设置颜色
self.colour = (255, 255, 200)
# 设置大小
self.size = size - 2
if self.size < 0:
self.size = 0
# 获取轨迹位置
def get_pos(self, x, y):
self.pos = vector(x, y)
# 显示轨迹
def show(self, win):
pygame.draw.circle(win, self.colour, (int(self.pos.x), int(self.pos.y)), self.size)
# 更新烟花
def update(win, fireworks):
# 遍历每个烟花
for fw in fireworks:
# 更新烟花
fw.update(win)
# 如果需要移除烟花
if fw.remove():
# 移除烟花
fireworks.remove(fw)
# 更新显示
pygame.display.update()
#主程序
def main():
#初始化pygame
pygame.init()
# 初始化字体
pygame.font.init()
# 设置窗口标题
pygame.display.set_caption("祝您新年快乐")
# 加载背景图片
background = pygame.image.load("./5.png")
# 加载音乐
sound_wav = pygame.mixer.music.load("2.mp3")
# 播放音乐
pygame.mixer.music.play()
pygame.init()
# 加载背景音乐
'''pygame.mixer.music.load("./res/音乐文件名")
# 循环播放背景音乐
pygame.mixer.music.play(-1)
# 停止背景音乐
pygame.mixer.music.stop()
# 加载音效
boom_sound = pygame.mixer.Sound("./res/音效名")
# 播放音效
boom_sound.play()
boom_sound.stop()
myfont = pygame.font.Font("simkai.TTF", 80)
myfont1 = pygame.font.Font("simkai.ttf", 30)
testsurface = myfont.render("虎虎生威", False, (0, 0, 0), (220, 20, 60))
testsurface1 = myfont1.render("", False, (251, 59, 85))'''
# pygame.image.load("")
# 创建窗口
win = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
# win.blit(background)
# 创建时钟
clock = pygame.time.Clock()
# 创建初始烟花
fireworks = [Firework() for i in range(2)] # create the first fireworks
running = True
# 游戏循环
while running:
# 设置帧率
clock.tick(60)
# 处理事件
for event in pygame.event.get():
# 如果是退出事件
if event.type == pygame.QUIT:
# 停止运行
running = False
# 如果是按键事件
if event.type == pygame.KEYDOWN:
# 如果按下1键
if event.key == pygame.K_1:
# 添加一个烟花
fireworks.append(Firework())
# 按下 2 加入10个烟花
if event.key == pygame.K_2:
for i in range(10):
fireworks.append(Firework())
# 按下 3 加入100个烟花
if event.key == pygame.K_3:
for i in range(100):
fireworks.append(Firework())
# 绘制背景
win.fill((20, 20, 30))
#win.blit(background, (0, 0))
#win.blit(testsurface, (200, 30))
#win.blit(testsurface1, (520, 80))
# 随机创建新的烟花
if randint(0, 20) == 1:
fireworks.append(Firework())
# 更新烟花
update(win, fireworks)
# 退出pygame
pygame.quit()
quit()
# 如果运行的是主程序
if __name__ == 'main':
# 运行主程序
main()
领取专属 10元无门槛券
私享最新 技术干货