pthon烟花代码 -- 超详细!新年烟花代码逐行解析(可更换烟花背景图)

在这篇博客中,我们将深入剖析一个使用 Python 的 Pygame 库实现的新年烟花效果代码。这个代码通过创建烟花和粒子对象,模拟了烟花在夜空中绽放的绚丽场景。接下来,我们会分段解释每个函数的用法,同时指出哪些参数可以改动以及改动后会产生什么样的效果。

先来看看整体代码。

import pygame
import random
import math

# 初始化pygame
pygame.init()

# 设置窗口大小
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("新年烟花")

# 定义颜色列表
COLORS = [
    (255, 0, 0), (0, 255, 0), (0, 0, 255),
    (255, 255, 0), (255, 0, 255), (0, 255, 255),
    (255, 128, 0), (128, 0, 255), (0, 128, 255),
    (255, 20, 147), (50, 205, 50), (218, 165, 32)
]

# 尝试加载底图
try:
    background = pygame.image.load(r"C:\Users\zh\Desktop\869155184d2b9b789c89e244b492cbf9_00003.jpg")  # 请替换为你自己的底图文件名
    background = pygame.transform.scale(background, (WIDTH, HEIGHT))
except pygame.error:
    print("底图加载失败,将使用黑色背景。")
    background = None

# 设置文字,使用支持中文的字体
font = pygame.font.Font(None, 60)  # 确保 simhei.ttf 存在,或者指定完整路径
text = font.render("2025 Happy New Year!", True, (255, 255, 255))
text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 2))


class Particle:
    def __init__(self, x, y, color, speed, angle, life_decay=0.1):
        self.x = x
        self.y = y
        self.color = color
        self.speed = speed
        self.angle = angle
        self.lifetime = random.randint(20, 40)
        self.life_decay = life_decay
        self.size = random.randint(1, 3)  # 随机粒子大小
        self.remove = False

    def update(self):
        self.x += self.speed * math.cos(self.angle)
        self.y += self.speed * math.sin(self.angle)
        self.speed *= 0.9
        self.lifetime -= self.life_decay
        if self.lifetime <= 0 or self.x < 0 or self.x > WIDTH or self.y < 0 or self.y > HEIGHT:
            self.remove = True

    def draw(self, screen):
        if self.lifetime > 0:
            alpha = int((self.lifetime / 40) * 255)
            s = pygame.Surface((self.size * 2, self.size * 2), pygame.SRCALPHA)
            pygame.draw.circle(s, (*self.color, alpha), (self.size, self.size), self.size)
            screen.blit(s, (int(self.x - self.size), int(self.y - self.size)))


class Firework:
    def __init__(self):
        self.x = random.randint(0, WIDTH)
        self.y = HEIGHT
        self.color = random.choice(COLORS)
        self.speed = random.randint(8, 12)
        self.exploded = False
        self.particles = []
        self.trail = []
        self.trail_length = 10
        self.remove = False

    def update(self):
        if not self.exploded:
            self.trail.append((self.x, self.y))
            if len(self.trail) > self.trail_length:
                self.trail.pop(0)
            self.y -= self.speed
            self.speed -= 0.1
            if self.speed <= 0:
                self.explode()
            elif self.y < 0:
                self.remove = True
        else:
            for particle in self.particles[:]:
                particle.update()
                if particle.remove:
                    self.particles.remove(particle)
            if len(self.particles) == 0:
                self.remove = True

    def explode(self):
        self.exploded = True
        num_particles = random.randint(150, 250)
        # 随机决定是花瓣状还是圆形
        is_petal = random.random() < 0.5
        if is_petal:
            num_petals = random.randint(3, 48)  # 随机花瓣数量
            petal_angle = 2 * math.pi / num_petals
            for i in range(num_particles):
                petal_index = i % num_petals
                base_angle = petal_index * petal_angle
                angle_variation = random.uniform(-math.pi / 12, math.pi / 12)
                angle = base_angle + angle_variation
                speed = random.uniform(1, 5)
                color = random.choice(COLORS)
                particle = Particle(self.x, self.y, color, speed, angle)
                self.particles.append(particle)
        else:
            for _ in range(num_particles):
                angle = random.uniform(0, 2 * math.pi)
                speed = random.uniform(1, 5)
                color = random.choice(COLORS)
                particle = Particle(self.x, self.y, color, speed, angle)
                self.particles.append(particle)

    def draw(self, screen):
        if not self.exploded:
            for i, (tx, ty) in enumerate(self.trail):
                alpha = int((i + 1) / len(self.trail) * 255)
                s = pygame.Surface((2, 2), pygame.SRCALPHA)
                pygame.draw.circle(s, (*self.color, alpha), (1, 1), 1)
                screen.blit(s, (int(tx - 1), int(ty - 1)))
            pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), 2)
        else:
            for particle in self.particles:
                particle.draw(screen)


# 创建烟花列表
fireworks = []

clock = pygame.time.Clock()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 每帧有一定概率生成新的烟花
    if random.random() < 0.04:
        fireworks.append(Firework())

    if background:
        screen.blit(background, (0, 0))
    else:
        screen.fill((0, 0, 0))

    screen.blit(text, text_rect)  # 绘制文字

    for firework in fireworks[:]:
        firework.update()
        firework.draw(screen)
        if firework.remove:
            fireworks.remove(firework)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

再来看看效果如何:
在这里插入图片描述
下面我会详细解释每一段代码的作用,以及各种参数的作用和更改之后的影响。

1. 导入库和初始化部分

import pygame
import random
import math

# 初始化pygame
pygame.init()

# 设置窗口大小
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("新年烟花")

代码解释

  • import pygameimport randomimport math:导入 Pygame 库用于图形绘制和动画处理,random 库用于生成随机数,math 库用于数学计算。
  • pygame.init():初始化 Pygame 的所有模块,为后续的操作做好准备。
  • WIDTH, HEIGHT = 800, 600:定义窗口的宽度和高度。
  • screen = pygame.display.set_mode((WIDTH, HEIGHT)):创建一个指定大小的窗口,并返回一个用于绘制的 Surface 对象。
  • pygame.display.set_caption("新年烟花"):设置窗口的标题为“新年烟花”。

可改动参数及效果

  • WIDTHHEIGHT:修改窗口的大小。增大数值会使窗口变大,烟花和文字会在更大的区域内显示;减小数值则会使窗口变小。

2. 颜色列表和背景设置部分

# 定义颜色列表
COLORS = [
    (255, 0, 0), (0, 255, 0), (0, 0, 255),
    (255, 255, 0), (255, 0, 255), (0, 255, 255),
    (255, 128, 0), (128, 0, 255), (0, 128, 255),
    (255, 20, 147), (50, 205, 50), (218, 165, 32)
]

# 尝试加载底图
try:
    background = pygame.image.load(r"C:\Users\zh\Desktop\869155184d2b9b789c89e244b492cbf9_00003.jpg")  # 请替换为你自己的底图文件名
    background = pygame.transform.scale(background, (WIDTH, HEIGHT))
except pygame.error:
    print("底图加载失败,将使用黑色背景。")
    background = None

代码解释

  • COLORS:定义了一个包含多种 RGB 颜色元组的列表,用于随机选择烟花和粒子的颜色。
  • pygame.image.load():尝试加载指定路径的图片作为背景图。
  • pygame.transform.scale():将加载的图片缩放为窗口的大小。
  • except 块:如果图片加载失败,会打印错误信息,并将 background 设为 None,后续会使用黑色背景。

可改动参数及效果

  • COLORS 列表:可以添加、删除或修改颜色元组,从而改变烟花和粒子的颜色。
  • pygame.image.load() 中的图片路径:更换为其他图片的路径,可改变窗口的背景图。

3. 文字设置部分

# 设置文字,使用支持中文的字体
font = pygame.font.Font(None, 60)  # 确保 simhei.ttf 存在,或者指定完整路径
text = font.render("2025 Happy New Year!", True, (255, 255, 255))
text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 2))

代码解释

  • pygame.font.Font(None, 60):创建一个字体对象,None 表示使用系统默认字体,60 是字体的大小。
  • font.render():将指定的文字渲染为一个 Surface 对象,True 表示开启抗锯齿,(255, 255, 255) 是文字的颜色(白色)。
  • text.get_rect(center=(WIDTH // 2, HEIGHT // 2)):获取文字的矩形区域,并将其中心位置设置为窗口的中心。

可改动参数及效果

  • None:可以替换为具体的字体文件路径(如 'simhei.ttf'),以使用特定的字体。
  • 60:修改字体的大小。
  • "2025 Happy New Year!":修改显示的文字内容。
  • (255, 255, 255):修改文字的颜色。

4. Particle 类部分

class Particle:
    def __init__(self, x, y, color, speed, angle, life_decay=0.1):
        self.x = x
        self.y = y
        self.color = color
        self.speed = speed
        self.angle = angle
        self.lifetime = random.randint(20, 40)
        self.life_decay = life_decay
        self.size = random.randint(1, 3)  # 随机粒子大小
        self.remove = False

    def update(self):
        self.x += self.speed * math.cos(self.angle)
        self.y += self.speed * math.sin(self.angle)
        self.speed *= 0.9
        self.lifetime -= self.life_decay
        if self.lifetime <= 0 or self.x < 0 or self.x > WIDTH or self.y < 0 or self.y > HEIGHT:
            self.remove = True

    def draw(self, screen):
        if self.lifetime > 0:
            alpha = int((self.lifetime / 40) * 255)
            s = pygame.Surface((self.size * 2, self.size * 2), pygame.SRCALPHA)
            pygame.draw.circle(s, (*self.color, alpha), (self.size, self.size), self.size)
            screen.blit(s, (int(self.x - self.size), int(self.y - self.size)))

代码解释

__init__ 方法
  • 初始化粒子的属性,包括位置 (x, y)、颜色 color、速度 speed、角度 angle、生命周期 lifetime、生命周期衰减率 life_decay、大小 size 以及是否移除的标志 remove
update 方法
  • 根据速度和角度更新粒子的位置。
  • 速度按一定比例衰减。
  • 生命周期按 life_decay 递减。
  • 如果生命周期小于等于 0 或者粒子超出窗口范围,将 remove 标志设为 True,表示需要移除该粒子。
draw 方法
  • 如果粒子的生命周期大于 0,计算其透明度 alpha
  • 创建一个透明的 Surface 对象,并在其上绘制一个圆形表示粒子。
  • 将该 Surface 对象绘制到屏幕上。

可改动参数及效果

  • life_decay:修改粒子生命周期的衰减率。增大该值,粒子会更快地消失;减小该值,粒子会存在更长时间。
  • random.randint(20, 40):修改粒子的初始生命周期范围。增大范围,粒子会存在更长时间;减小范围,粒子会更快消失。
  • random.randint(1, 3):修改粒子的大小范围。增大范围,粒子会更大;减小范围,粒子会更小。

5. Firework 类部分

class Firework:
    def __init__(self):
        self.x = random.randint(0, WIDTH)
        self.y = HEIGHT
        self.color = random.choice(COLORS)
        self.speed = random.randint(8, 12)
        self.exploded = False
        self.particles = []
        self.trail = []
        self.trail_length = 10
        self.remove = False

    def update(self):
        if not self.exploded:
            self.trail.append((self.x, self.y))
            if len(self.trail) > self.trail_length:
                self.trail.pop(0)
            self.y -= self.speed
            self.speed -= 0.1
            if self.speed <= 0:
                self.explode()
            elif self.y < 0:
                self.remove = True
        else:
            for particle in self.particles[:]:
                particle.update()
                if particle.remove:
                    self.particles.remove(particle)
            if len(self.particles) == 0:
                self.remove = True

    def explode(self):
        self.exploded = True
        num_particles = random.randint(150, 250)
        # 随机决定是花瓣状还是圆形
        is_petal = random.random() < 0.5
        if is_petal:
            num_petals = random.randint(3, 48)  # 随机花瓣数量
            petal_angle = 2 * math.pi / num_petals
            for i in range(num_particles):
                petal_index = i % num_petals
                base_angle = petal_index * petal_angle
                angle_variation = random.uniform(-math.pi / 12, math.pi / 12)
                angle = base_angle + angle_variation
                speed = random.uniform(1, 5)
                color = random.choice(COLORS)
                particle = Particle(self.x, self.y, color, speed, angle)
                self.particles.append(particle)
        else:
            for _ in range(num_particles):
                angle = random.uniform(0, 2 * math.pi)
                speed = random.uniform(1, 5)
                color = random.choice(COLORS)
                particle = Particle(self.x, self.y, color, speed, angle)
                self.particles.append(particle)

    def draw(self, screen):
        if not self.exploded:
            for i, (tx, ty) in enumerate(self.trail):
                alpha = int((i + 1) / len(self.trail) * 255)
                s = pygame.Surface((2, 2), pygame.SRCALPHA)
                pygame.draw.circle(s, (*self.color, alpha), (1, 1), 1)
                screen.blit(s, (int(tx - 1), int(ty - 1)))
            pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), 2)
        else:
            for particle in self.particles:
                particle.draw(screen)

代码解释

__init__ 方法
  • 初始化烟花的属性,包括位置 (x, y)、颜色 color、速度 speed、是否爆炸的标志 exploded、粒子列表 particles、轨迹列表 trail、轨迹长度 trail_length 以及是否移除的标志 remove
update 方法
  • 如果烟花还未爆炸,更新其位置和速度,添加轨迹点,并根据速度判断是否爆炸。如果烟花超出窗口顶部,将 remove 标志设为 True
  • 如果烟花已经爆炸,更新每个粒子的状态,并移除生命周期结束的粒子。如果所有粒子都已移除,将 remove 标志设为 True
explode 方法
  • exploded 标志设为 True,表示烟花爆炸。
  • 随机生成一定数量的粒子(150 - 250 个)。
  • 随机决定烟花爆炸的形状是花瓣状还是圆形,并根据不同形状生成相应的粒子。
draw 方法
  • 如果烟花还未爆炸,绘制烟花的轨迹和烟花本身。
  • 如果烟花已经爆炸,绘制所有的粒子。

可改动参数及效果

  • random.randint(8, 12):修改烟花上升的初始速度范围。增大范围,烟花会上升得更快;减小范围,烟花会上升得更慢。
  • trail_length:修改烟花轨迹的长度。增大该值,轨迹会更长;减小该值,轨迹会更短。
  • random.randint(150, 250):修改烟花爆炸时生成的粒子数量范围。增大范围,烟花爆炸会更绚丽;减小范围,烟花爆炸会相对暗淡。
  • random.randint(3, 48):在花瓣状爆炸时,修改花瓣的数量范围。增大范围,花瓣会更多;减小范围,花瓣会更少。

6. 主循环部分

# 创建烟花列表
fireworks = []

clock = pygame.time.Clock()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 每帧有一定概率生成新的烟花
    if random.random() < 0.04:
        fireworks.append(Firework())

    if background:
        screen.blit(background, (0, 0))
    else:
        screen.fill((0, 0, 0))

    screen.blit(text, text_rect)  # 绘制文字

    for firework in fireworks[:]:
        firework.update()
        firework.draw(screen)
        if firework.remove:
            fireworks.remove(firework)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

代码解释

  • fireworks = []:创建一个空列表,用于存储所有的烟花对象。
  • clock = pygame.time.Clock():创建一个时钟对象,用于控制游戏的帧率。
  • while running 循环:主循环,不断更新和绘制画面,直到用户关闭窗口。
  • pygame.event.get():获取所有的事件,检查是否有用户关闭窗口的事件。
  • if random.random() < 0.04:每帧有 4% 的概率生成一个新的烟花。
  • screen.blit(background, (0, 0))screen.fill((0, 0, 0)):绘制背景图或填充黑色背景。
  • screen.blit(text, text_rect):绘制文字。
  • 遍历 fireworks 列表,更新和绘制每个烟花,并移除需要移除的烟花。
  • pygame.display.flip():更新整个屏幕的显示。
  • clock.tick(60):控制游戏的帧率为 60 帧每秒。
  • pygame.quit():退出 Pygame。

可改动参数及效果

  • 0.04:修改生成新烟花的概率。增大该值,会更频繁地生成新烟花;减小该值,生成新烟花的频率会降低。
  • 60:修改游戏的帧率。增大该值,画面会更流畅,但可能会增加 CPU 负担;减小该值,画面会变得卡顿。

如果你没有合适的背景,可以用下面的背景来欣赏这一场电子烟花秀。
在这里插入图片描述

通过以上的详细解释,相信你对这个新年烟花代码有了更深入的理解。你可以根据自己的需求修改参数,创造出独一无二的烟花效果。快去试试吧!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值