# 环境

• 操作系统：Windows
• Python 版本：3.6
• 涉及模块：tkinter、PIL、time、random、math

# 实现

#### 导入库

```import tkinter as tk
from PIL import Image, ImageTk
from time import time, sleep
from random import choice, uniform, randint
from math import sin, cos, radians```

#### 烟花颜色

`colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple', 'seagreen', 'indigo', 'cornflowerblue']`

#### 定义烟花类

```class fireworks:
def __init__(self, cv, idx, total, explosion_speed, x=0., y=0., vx=0., vy=0., size=2., color='red', lifespan=2, **kwargs):
self.id = idx
# 烟花绽放 x 轴
self.x = x
# 烟花绽放 x 轴
self.y = y
self.initial_speed = explosion_speed
# 外放 x 轴速度
self.vx = vx
# 外放 y 轴速度
self.vy = vy
# 绽放的粒子数
self.total = total
# 已停留时间
self.age = 0
# 颜色
self.color = color
# 画布
self.cv = cv
self.cid = self.cv.create_oval(x - size, y - size, x + size, y + size,
fill=self.color)
self.lifespan = lifespan

# 更新数据
def update(self, dt):
self.age += dt
# 粒子膨胀
if self.alive() and self.expand():
move_x = cos(radians(self.id * 360 / self.total)) * self.initial_speed
move_y = sin(radians(self.id * 360 / self.total)) * self.initial_speed
self.cv.move(self.cid, move_x, move_y)
self.vx = move_x / (float(dt) * 1000)
# 膨胀到最大下落
elif self.alive():
move_x = cos(radians(self.id * 360 / self.total))
self.cv.move(self.cid, self.vx + move_x, self.vy + 0.5 * dt)
self.vy += 0.5 * dt
# 过期移除
elif self.cid is not None:
cv.delete(self.cid)
self.cid = None

# 定义膨胀效果的时间帧
def expand(self):
return self.age <= 1.5

# 检查粒子是否仍在生命周期内
def alive(self):
return self.age <= self.lifespan```

#### 燃放烟花

```def ignite(cv):
t = time()
# 烟花列表
explode_points = []
wait_time = randint(10, 100)
# 爆炸的个数
numb_explode = randint(6, 10)
for point in range(numb_explode):
# 爆炸粒子列表
objects = []
# 爆炸 x 轴
x_cordi = randint(50, 550)
# 爆炸 y 轴
y_cordi = randint(50, 150)
speed = uniform(0.5, 1.5)
size = uniform(0.5, 3)
color = choice(colors)
# 爆炸的绽放速度
explosion_speed = uniform(0.2, 1)
# 爆炸的粒子数半径
total_particles = randint(10, 50)
for i in range(1, total_particles):
r = fireworks(cv, idx=i, total=total_particles, explosion_speed=explosion_speed, x=x_cordi, y=y_cordi,
vx=speed, vy=speed, color=color, size=size,
lifespan=uniform(0.6, 1.75))
# 添加进粒子列表里
objects.append(r)
# 把粒子列表添加到烟花列表
explode_points.append(objects)
total_time = .0
# 在 1.8 秒时间帧内保持更新
while total_time < 1.8:
# 让画面暂停 0.01s
sleep(0.01)
# 刷新时间
tnew = time()
t, dt = tnew, tnew - t
# 遍历烟花列表
for point in explode_points:
# 遍历烟花里的粒子列表
for item in point:
# 更新时间
item.update(dt)
# 刷新页面
cv.update()
total_time += dt
root.after(wait_time, ignite, cv)```

#### 启动

```if __name__ == "__main__":
root = tk.Tk()
# 绘制一个画布
cv = tk.Canvas(root, height=400, width=600)
# 背景图
image = Image.open("bg.jpg")
photo = ImageTk.PhotoImage(image)
# 在画板上绘制一张图片
cv.create_image(0, 0, image=photo, anchor='nw')
cv.pack()
root.protocol(close)
root.after(100, ignite, cv)
# 生成窗口
root.mainloop()```

0 条评论

• ### 你的童年有俄罗斯方块吗？教你用 Python 实现俄罗斯方块！

还是为数不多的游戏类电子产品，对小孩子更是有着不可抗拒的魔力，在当时如果哪个小孩买了一个小游戏机，大伙一定迅速围上去...

• ### 5 分钟教你用 Python 实现贪吃蛇！

贪吃蛇作为一款经典小游戏，早在 1976 年就面世了，我最早接触它还是在家长的诺基亚手机中。

• ### 经典 90 坦克大战 Python 版实现（支持单双人模式）

坦克大战是一个比较经典的小游戏，而 90 坦克大战是一个比较经典的版本，我们来看一下如何利用 Python 实现坦克大战，先睹为快。

• ### 用Python实现模拟登录正方教务系统抢课

最近学校开始选课，但是如果选课时间与自己的事情冲突，这时候就可以使用Python脚本自助抢课，抢课的第一步即是模拟登录，需要模拟登录后保存登录信息然后再进行操作...

• ### 如何用vn.py做隔夜交易？

本文提供了一个每个交易日开盘前不用重连CTP的方法。如果不是特殊需求，强烈建议每天盘前重启程序。感谢viponedream在维恩的派论坛里的分享！

• ### Python学习——数据模型/特殊方法

数据模型其实是对Python框架的描述，它规范了这门语言自身构架模块的接口，这些模块包括但不限于序列、迭代器、函数、类和上下文管理器。简单来说，数据模型就是Py...

• ### vn.py入门-低买高卖示例

本文用一个例子来介绍vnpy的用法。从项目创建开始，到一个简单策略的设计。 这个例子连接到CTP接口，每秒检查一下目标合约的价格，若低于指定价格则买入，若高于指...

• ### python实现opencv+scoket网络实时图传

本文实例为大家分享了python实现opencv+scoket网络实时图传的具体代码，供大家参考，具体内容如下