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

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

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

最终结果

文章目录

      • 博客:Python实现过年烟花效果及打包成可执行文件
    • 1. 程序结构概述
    • 2. Pygame初始化与屏幕设置
    • 3. 颜色与字体定义
    • 4. 烟花粒子类
    • 5. 烟花类
    • 6. 文字效果
    • 7. 主循环
    • 8. 打包成可执行文件
      • 8.1 安装 PyInstaller
      • 8.2 打包脚本
      • 8.3 获取可执行文件
      • 8.4 下载源代码与打包好的文件
    • 9. 总结


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新年快乐

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/956358.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新星杯-ESP32智能硬件开发--ESP32的I/O组成-系统中断矩阵

本博文内容导读&#x1f4d5;&#x1f389;&#x1f525; ESP32开发板的中断矩阵、功能描述与实现、相关API和示例程序进行介绍 ESP32中断矩阵将任一外部中断源单独分配到每个CPU的任一外部中断上&#xff0c;提供了强大的灵活性&#xff0c;能适应不同的应用需求。 ESP32中断主…

SpringBoot2 + Flowable(UI)

文章目录 引言I 技术栈软件架构基于 Vue.js 和 Element UI 的后台管理系统工程结构II 依赖rest,logic,conf 的依赖工作流flowable jar包flowable-ui所需jar包III 配置jdbc 配置 nullCatalogMeansCurrent = true引言 I 技术栈 软件架构 前端基于vue 、element-ui框架分模块设…

.Net 6.0 .Net7.0 .Net8.0 .Net9.0 使用 Serilog 按日志等级写入日志及 appsetting.json 配置方式实现

前言 最近使用最新版的Serilog记录日志时&#xff0c;发现以前有些关于Serilog的Nuget弃用了&#xff0c;最关键的是有些配置写法也改变&#xff0c;于是就整理了一下最新版的Serilog配置方式(appsetting.json)的使用 说明&#xff1a;我是用的.Net6&#xff0c;最新长期支持…

sprnigboot集成Memcached

安装Memcached 下载地址 32位系统 1.2.5版本&#xff1a;http://static.jyshare.com/download/memcached-1.2.5-win32-bin.zip 32位系统 1.2.6版本&#xff1a;http://static.jyshare.com/download/memcached-1.2.6-win32-bin.zip 32位系统 1.4.4版本&#xff1a;http://stati…

【数据分析】02- A/B 测试:玩转假设检验、t 检验与卡方检验

一、背景&#xff1a;当“审判”成为科学 1.1 虚拟场景——法庭审判 想象这样一个场景&#xff1a;有一天&#xff0c;你在王国里担任“首席审判官”。你面前站着一位嫌疑人&#xff0c;有人指控他说“偷了国王珍贵的金冠”。但究竟是他干的&#xff0c;还是他是被冤枉的&…

3dmax LOGO的符号、意义和历史,渲染100邀请码1a12

Autodesk 3ds Max 是一款 3D 建模、动画和渲染软件&#xff0c;由 Autodesk, Inc. 于 1996 年开发&#xff0c;其功能是能够创建复杂的数字场景和视觉效果&#xff0c;被专业建筑师、设计师和视频游戏创作者广泛使用&#xff0c;提供了七种语言的 Windows 版本&#xff0c;没有…

线段树优化dp,abc389F - Rated Range

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 F - Rated Range 二、解题报告 1、思路分析 考虑定义 f(i, j) 为 初始分…

青少年CTF练习平台 EasyMD5解题思路

题目 EasyMD5 PHP弱类型/弱等于的判断 翻译 上传之后网页提示&#xff1a;Not a PDF! angry!!! get out from my page 修改文件后缀为pdf 再次上传&#xff0c;答案出来了 s878926199a s155964671a 成功获取flag

Amazon MSK 开启 Public 访问 SASL 配置的方法

1. 开启 MSK Public 1.1 配置 MSK 参数 进入 MSK 控制台页面&#xff0c;点击左侧菜单 Cluster configuration。选择已有配置&#xff0c;或者创建新配置。在配置中添加参数 allow.everyone.if.no.acl.foundfalse修改集群配置&#xff0c;选择到新添加的配置。 1.2 开启 Pu…

SW - 钣金零件保存成DWG时,需要将折弯线去掉

文章目录 SW - 钣金零件保存成DWG时&#xff0c;需要将折弯线去掉概述笔记备注END SW - 钣金零件保存成DWG时&#xff0c;需要将折弯线去掉 概述 如果做需要弯折的切割件&#xff0c;最好做成钣金零件。 最近做了几个小钣金(将钣金展开&#xff0c;建立新草图&#xff0c;在2…

深度学习 Pytorch 基本优化思想与最小二乘法

在正式开始进行神经网络建模之前&#xff0c;我们还需要掌握pytorch中最核心的基础数学工具——autograd(自动微分)模块。虽然对于任何一个通用的深度学习框架都会提供许多自动优化的算法和现成的loss function&#xff0c;但如果想更深入理解神经网络&#xff0c;对深度学习的…

Ceph与RAID在存储中的协同工作过程

本文将结合架构图&#xff0c;详细讲解Ceph与RAID如何在存储环境中相互配合&#xff0c;共同提供高效且可靠的存储服务。 架构概述 从上图中可以看到&#xff0c;Ceph的架构主要分为四个层次&#xff1a; 客户端和服务接口层&#xff1a;这一层包括客户端访问存储应用的接口…

PyTest自学-认识PyTest

1 PyTest自学-认识PyTest 1.1 PyTest可以用来做什么&#xff1f; PyTest是一个自动化测试框架&#xff0c;支持单元测试和功能测试&#xff0c;有丰富的插件&#xff0c;如&#xff0c;pytest-selemium, pytest-html等。 1.2 安装pytest 使用pip install -U pytest。 1.3 py…

【MathType】mathtype在word中格式问题

【MathType】mathtype在word中格式问题 1. 问题解决方法效果 2.新的问题解决方法效果 1. 问题 mathtype在word中格式显示不全 解决方法 CtrlC&#xff1a;选中全部——>段落——>设置为单倍行距 效果 已经可以全部显示出来&#xff0c;但是还有新问题&#xff01;…

当设置dialog中有el-table时,并设置el-table区域的滚动,看到el-table中多了一条横线

问题&#xff1a;当设置dialog中有el-table时&#xff0c;并设置el-table区域的滚动&#xff0c;看到el-table中多了一条横线&#xff1b; 原因&#xff1a;el-table有一个before的伪元素作为表格的下边框下&#xff0c;初始的时候已设置&#xff0c;在滚动的时候并没有重新设置…

华为AI培训-NLP实验

中文分词、命名实体识别、语义词性标注、语句逻辑推理、文本摘要、机器翻译、文本情感分析、内容创作 1 实验介绍 1.1 实验背景 中文分词、命名实体识别、语义词性标注、语句逻辑推理是自然语言处理领域中的重要任务。中文分词是将连续的汉字序列切分成有意义的词语序列…

一文大白话讲清楚webpack基本使用——4——vue-loader的配置和使用

一文大白话讲清楚webpack基本使用——4——vue-loader的配置和使用 1. 建议按文章顺序从头看是看 第一篇&#xff1a;一文大白话讲清楚啥是个webpack第二篇&#xff1a;一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建第三篇一文大白话讲清楚webpack基本使用…

【从零开始入门unity游戏开发之——C#篇46】C#补充知识点——命名参数和可选参数

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…

< OS 有关 > 阿里云:轻量应用服务器 的使用 安装 Tailscale 后DNS 出错, 修复并替换 apt 数据源

VPS 配置 主机&#xff1a;vCPU x2, 512MB, 20GB位置&#xff1a;阿里云&#xff0c;日本.东京OS&#xff1a; ubuntu24.20 原因&#xff1a; 这篇是操作过程的记录文章。 2 个月前&#xff0c; 在阿里云买了台 vps 。当时本想放到韩国&#xff0c;因为它离北京近。 但最便…

第6章 ThreadGroup详细讲解(Java高并发编程详解:多线程与系统设计)

1.ThreadGroup 与 Thread 在Java程序中&#xff0c; 默认情况下&#xff0c; 新的线程都会被加入到main线程所在的group中&#xff0c; main线程的group名字同线程名。如同线程存在父子关系一样&#xff0c; Thread Group同样也存在父子关系。图6-1就很好地说明了父子thread、父…