Python帶你跨年!用Python送你一場跨年煙花秀

Python小二發表於2021-12-30

2021 已經接近尾聲了,2022 即將到來,本文我們用 Python 送你一場跨年煙花秀。

我們用到的 Python 模組包括:tkinter、PIL、time、random、math,如果第三方模組沒有裝的話,pip install 一下即可,下面看一下程式碼實現。

導庫

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小二後臺回覆f獲取~

相關文章