专栏首页Python小二用 Python 实现一场环保无污染的烟花秀

用 Python 实现一场环保无污染的烟花秀

烟花由中国古代人民较早发明,常用于盛大的典礼或表演中,也在除夕夜及元宵节中燃放用来烘托节日氛围。近年来随着环境污染的加剧,一些地区已经禁止燃放烟花了,那我们就用 Python 实现一场无污染的烟花秀。

环境

  • 操作系统: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()

最终效果,如图所示:

本文分享自微信公众号 - Python小二(chengxuzhijian),作者:程序员野客

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 你的童年有俄罗斯方块吗?教你用 Python 实现俄罗斯方块!

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

    Python小二
  • 5 分钟教你用 Python 实现贪吃蛇!

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

    Python小二
  • 经典 90 坦克大战 Python 版实现(支持单双人模式)

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

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

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

    sergiojune
  • 如何用vn.py做隔夜交易?

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

    用Python的交易员
  • Python学习——数据模型/特殊方法

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

    陆勤_数据人网
  • vn.py入门-低买高卖示例

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

    用Python的交易员
  • 教你制作可移动的导航栏

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

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

    砸漏
  • IOS 自定义UITableViewCell 常用

    用户5760343

扫码关注云+社区

领取腾讯云代金券