自学内容网 自学内容网

Python实现过年烟花效果及打包成可执行文件

博客:Python实现过年烟花效果及打包成可执行文件

在这篇博客中,我们将详细讲解如何使用Python和Pygame库实现一个过年烟花效果的程序,并介绍如何将Python脚本打包成Windows上可以直接执行的exe文件。我们将从代码的各个模块入手,逐步解析其实现原理,并最终介绍如何使用打包工具将程序打包成可执行文件。

最终结果


1. 程序结构概述

该程序主要由以下几个模块组成:

  1. Pygame初始化与屏幕设置:初始化Pygame并设置屏幕大小。
  2. 颜色与字体定义:定义烟花和文字的颜色,并加载书法字体。
  3. 烟花粒子类:定义烟花爆炸后的粒子效果。
  4. 烟花类:定义烟花的发射、爆炸和绘制逻辑。
  5. 文字效果:实现七彩渐变文字的绘制。
  6. 主循环:控制烟花的生成、移动、爆炸以及文字的滚动显示。

接下来,我们将逐一讲解这些模块的实现细节。


2. Pygame初始化与屏幕设置

import pygame
import random
import math
import os

# 初始化pygame
pygame.init()

# 设置屏幕大小(17:9比例)
screen_width = 1700
screen_height = 900
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("过年烟花效果")
  • Pygame初始化pygame.init() 是Pygame库的初始化函数,用于启动Pygame的所有模块。
  • 屏幕设置:我们设置了一个17:9比例的屏幕,宽度为1700像素,高度为900像素。pygame.display.set_mode() 用于创建屏幕对象,pygame.display.set_caption() 用于设置窗口标题。

3. 颜色与字体定义

# 定义颜色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
COLORS = [
    (255, 0, 0),  # 红色
    (255, 165, 0),  # 橙色
    (255, 255, 0),  # 黄色
    (0, 255, 0),  # 绿色
    (0, 0, 255),  # 蓝色
    (75, 0, 130),  # 靛色
    (238, 130, 238),  # 紫色
]

# 加载书法字体
font_path = "汇文港黑v1.001.ttf"
if not os.path.exists(font_path):
    raise FileNotFoundError(f"字体文件 {font_path} 未找到,请确保字体文件存在!")
font = pygame.font.Font(font_path, 99)  # 使用书法字体,大小为70
  • 颜色定义:我们定义了一些常见的颜色,包括黑色、白色以及彩虹七色。这些颜色将用于烟花粒子和文字的绘制。
  • 字体加载:我们加载了一个书法字体文件(汇文港黑v1.001.ttf,这是一个免费的字体,你可以在该链接找到分享原文【發佈】匯文系列字體),并设置了字体大小为99(就是取一个长长久久之意,强迫症患者可以改成100)。如果字体文件不存在,程序会抛出错误。

4. 烟花粒子类

class Particle:
    def __init__(self, x, y, color, effect_type):
        self.x = x
        self.y = y
        self.color = color
        self.radius = random.randint(2, 4)
        self.speed = random.uniform(1, 3)
        self.angle = random.uniform(0, 2 * math.pi)
        self.life = random.randint(20, 40)
        self.effect_type = effect_type  # 爆炸效果类型
        self.range_multiplier = random.uniform(0.5, 2.0)  # 随机范围参数

    def move(self):
        if self.effect_type == 1:  # 普通爆炸
            self.x += math.cos(self.angle) * self.speed * self.range_multiplier
            self.y += math.sin(self.angle) * self.speed * self.range_multiplier
        elif self.effect_type == 2:  # 环形爆炸
            self.angle += 0.05  # 缓慢旋转
            radius = self.life * self.range_multiplier  # 半径随时间变化
            self.x += math.cos(self.angle) * radius * 0.1
            self.y += math.sin(self.angle) * radius * 0.1
        elif self.effect_type == 3:  # 星形爆炸
            star_points = 5  # 星形的顶点数
            angle_step = (2 * math.pi) / star_points
            self.angle += 0.05  # 缓慢旋转
            radius = self.life * self.range_multiplier  # 半径随时间变化
            self.x += math.cos(self.angle * star_points) * radius * 0.1
            self.y += math.sin(self.angle * star_points) * radius * 0.1
        elif self.effect_type == 4:  # 心形爆炸
            t = self.life / 40  # 参数t,控制心形轨迹
            x_offset = 16 * (math.sin(t) ** 3)
            y_offset = -13 * math.cos(t) + 5 * math.cos(2 * t) + 2 * math.cos(3 * t) + math.cos(4 * t)
            self.x += x_offset * self.range_multiplier * 0.1
            self.y += y_offset * self.range_multiplier * 0.1
        elif self.effect_type == 5:  # 瀑布爆炸
            self.y += self.speed * self.range_multiplier  # 向下扩散
            self.x += math.cos(self.angle) * self.speed * 0.2  # 轻微水平扩散
        elif self.effect_type == 6:  # 螺旋上升爆炸
            self.angle += 0.1  # 螺旋角度变化
            radius = self.life * self.range_multiplier  # 半径随时间变化
            self.x += math.cos(self.angle) * radius * 0.1
            self.y -= math.sin(self.angle) * radius * 0.1  # 向上扩散

        self.life -= 1

    def draw(self):
        pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
  • 粒子初始化:每个粒子都有位置、颜色、半径、速度、角度、生命周期等属性。effect_type 决定了粒子的爆炸效果类型。
  • 粒子移动:根据 effect_type 的不同,粒子会以不同的方式移动。例如,普通爆炸、环形爆炸、星形爆炸、心形爆炸等。
  • 粒子绘制:使用 pygame.draw.circle() 绘制粒子。

这个部分代码比较多,不过都写了注释,需有修改的需要请按照注释修改。


5. 烟花类

class Firework:
    def __init__(self):
        self.x = random.randint(0, screen_width)
        self.y = screen_height
        self.color = random.choice(COLORS)
        self.particles = []
        self.exploded = False
        self.speed = 10  # 加快烟花发射速度
        self.effect_type = 1 if random.random() < 0.5 else random.randint(2, 6)

    def explode(self, displayed_sentences):
        # 检查烟花爆炸位置是否与字体重叠
        for sentence, x, y in displayed_sentences:
            text_width, text_height = font.size(sentence)
            if (
                self.x >= x - text_width // 2
                and self.x <= x + text_width // 2
                and self.y >= y - text_height // 2
                and self.y <= y + text_height // 2
            ):
                # 如果重叠,调整烟花爆炸位置
                self.x = random.randint(0, screen_width)
                self.y = random.randint(0, screen_height // 2)
                break

        particle_count = 150  # 增加粒子数量
        for _ in range(particle_count):
            particle = Particle(self.x, self.y, self.color, self.effect_type)
            self.particles.append(particle)
        self.exploded = True

    def move(self, displayed_sentences):
        if not self.exploded:
            self.y -= self.speed  # 使用更快的速度
            if self.y <= random.randint(100, 300):
                self.explode(displayed_sentences)
        else:
            for particle in self.particles:
                particle.move()

    def draw(self):
        if not self.exploded:
            pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), 5)
        else:
            for particle in self.particles:
                particle.draw()
  • 烟花初始化:烟花从屏幕底部随机位置发射,颜色随机,爆炸效果类型也随机。
  • 烟花爆炸:当烟花上升到一定高度时,会爆炸生成多个粒子。爆炸时会检查是否与文字重叠,如果重叠则调整爆炸位置。
  • 烟花移动与绘制:烟花在未爆炸时会向上移动,爆炸后会绘制所有粒子。

6. 文字效果

def draw_gradient_text(text, font, x, y, colors):
    text_surface = font.render(text, True, WHITE).convert_alpha()
    text_width = text_surface.get_width()
    text_height = text_surface.get_height()

    # 创建渐变颜色条
    gradient = pygame.Surface((text_width, text_height))
    for i in range(text_width):
        color_index = int((i / text_width) * (len(colors) - 1))
        color1 = colors[color_index]
        color2 = colors[color_index + 1] if color_index + 1 < len(colors) else colors[color_index]
        ratio = (i / text_width) * (len(colors) - 1) - color_index
        color = (
            int(color1[0] + (color2[0] - color1[0]) * ratio),
            int(color1[1] + (color2[1] - color1[1]) * ratio),
            int(color1[2] + (color2[2] - color1[2]) * ratio),
        )
        pygame.draw.line(gradient, color, (i, 0), (i, text_height))

    # 将渐变颜色条与文字结合
    text_surface.blit(gradient, (0, 0), special_flags=pygame.BLEND_MULT)
    screen.blit(text_surface, (x, y))
  • 渐变文字绘制:该函数实现了七彩渐变文字的绘制效果。首先渲染文字,然后创建一个渐变颜色条,最后将渐变颜色条与文字结合,形成渐变效果。

7. 主循环

clock = pygame.time.Clock()
fireworks = []

# 加载句子
sentences = load_sentences("words.txt")
current_sentence_index = 0
sentence_y = screen_height  # 初始位置在屏幕底部
displayed_sentences = []  # 存储已经显示的句子及其位置

# 计算句子的合适位置
def calculate_sentence_positions(sentences, font):
    margin = 20  # 句子之间的间距
    total_height = sum(font.size(sentence)[1] for sentence in sentences) + margin * (len(sentences) - 1)
    start_y = screen_height * 0.4 - total_height // 2  # 整体居中在屏幕40%的位置

    positions = []
    y = start_y
    for sentence in sentences:
        text_width, text_height = font.size(sentence)
        x = (screen_width - text_width) // 2
        positions.append((x, y))
        y += text_height + margin  # 下一句的位置

    return positions

# 计算所有句子的目标位置
sentence_positions = calculate_sentence_positions(sentences, font)

# 初始化时立即生成多个烟花
for _ in range(10):  # 生成10个烟花
    fireworks.append(Firework())

running = True
while running:
    screen.fill(BLACK)

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

    # 添加新的烟花
    if random.random() < 0.1:  # 增加烟花生成概率
        fireworks.append(Firework())

    # 更新和绘制烟花
    for firework in fireworks:
        firework.move(displayed_sentences)
        firework.draw()

    # 移除已经消失的烟花
    fireworks = [firework for firework in fireworks if not firework.exploded or any(particle.life > 0 for particle in firework.particles)]

    # 绘制当前句子
    if current_sentence_index < len(sentences):
        current_sentence = sentences[current_sentence_index]
        text_width, text_height = font.size(current_sentence)
        target_x, target_y = sentence_positions[current_sentence_index]

        # 如果句子未到达目标位置,继续滚动
        if sentence_y > target_y:
            draw_gradient_text(current_sentence, font, (screen_width - text_width) // 2, sentence_y, COLORS)
            sentence_y -= 5  # 控制字体滚动速度
        else:
            # 句子停止后,将其添加到已显示句子列表中
            displayed_sentences.append((current_sentence, target_x, target_y))
            current_sentence_index += 1  # 切换到下一句
            sentence_y = screen_height  # 重置到屏幕底部

    # 绘制所有已显示的句子
    for sentence, x, y in displayed_sentences:
        draw_gradient_text(sentence, font, x, y, COLORS)

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

pygame.quit()
  • 主循环:主循环负责控制程序的运行。它不断更新烟花的状态、绘制烟花和文字,并处理用户输入(如关闭窗口)。
  • 烟花生成与移除:每隔一段时间生成新的烟花,移除已经消失的烟花。
  • 文字滚动显示:文字从屏幕底部滚动到指定位置,形成动态效果。

8. 打包成可执行文件

为了将Python脚本打包成Windows上可以直接执行的exe文件,我们可以使用 PyInstaller 工具。以下是具体步骤:

8.1 安装 PyInstaller

首先,确保你已经安装了 PyInstaller。如果没有安装,可以使用以下命令进行安装:

pip install pyinstaller

8.2 打包脚本

在命令行中,导航到脚本所在的目录,然后运行以下命令:

pyinstaller --onefile --windowed 过年烟花.py
  • --onefile:将所有依赖打包成一个单独的exe文件。
  • --windowed:不显示命令行窗口(适用于GUI程序)。

这里有一点要特别注意,如果是第一次使用pyinstaller可能会出现这个bug

pyinstaller : 无法将“pyinstaller”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 1
+ pyinstaller --onefile --windowed 过年烟花.py
+ ~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (pyinstaller:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

这个原因pyinstaller没有加入环境变量导致的,Windows容易出现这个问题,快捷方案如下(交给解释器自己去处理):

python -m PyInstaller --onefile --windowed 过年烟花.py

打包成功

如果还有疑问可以参考我的另外一篇博客

打包成功后的文件目录

8.3 获取可执行文件

打包完成后,你可以在 dist 目录下找到生成的 过年烟花.exe 文件。你可以将这个文件分发给其他Windows用户,他们无需安装Python环境即可运行该程序。

此时要注意的是打包好的文件是个exe文件,但是我们之前使用的ttf文件和txt并不会自动打包进去,因为我们需要手动复制粘贴一下。直接放到exe文件的目录即可。


8.4 下载源代码与打包好的文件

百度网盘链接:通过网盘分享的文件:2025 过年烟花
链接: https://pan.baidu.com/s/1n8T54A8QiHGrw0H5bs3Wfw?pwd=49ht 提取码: 49ht

9. 总结

通过这篇博客,我们详细讲解了如何使用Python和Pygame实现一个过年烟花效果的程序,并介绍了如何将Python脚本打包成Windows上可以直接执行的exe文件。

希望这篇博客对你有所帮助,祝你在编程的道路上越走越远!同时也提前祝大家2025新年快乐。

2025新年快乐


原文地址:https://blog.csdn.net/FontThrone/article/details/145247287

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!