import tkinter as tk
import random
import math
import time

# 窗口设置
WIDTH = 800
HEIGHT = 600

root = tk.Tk()
root.title("Python 动态烟花")
canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="#000010")
canvas.pack()

# 颜色池
COLORS = ["#ff3333", "#ffdd33", "#33ff66", "#33ddff", "#dd33ff", "#ff9933", "#ffffff"]


class Particle:
    def __init__(self, x, y, speed, angle, color, size, life):
        self.x = x
        self.y = y
        self.vx = speed * math.cos(angle)
        self.vy = speed * math.sin(angle)
        self.color = color
        self.size = size
        self.life = life  # 剩余存活帧数
        self.max_life = life

    def update(self):
        # 重力模拟
        self.vy += 0.12
        self.x += self.vx
        self.y += self.vy
        self.life -= 1

    def draw(self):
        # 根据生命透明度缩放大小
        scale = self.life / self.max_life
        r = self.size * scale
        canvas.create_oval(
            self.x - r, self.y - r,
            self.x + r, self.y + r,
            fill=self.color, outline=self.color
        )


class FireWork:
    def __init__(self):
        # 烟花发射底部随机位置
        self.x = random.randint(80, WIDTH - 80)
        self.y = HEIGHT
        self.target_y = random.randint(80, HEIGHT // 2)
        self.speed = random.uniform(5, 8)
        self.exploded = False
        self.particles = []
        self.color = random.choice(COLORS)

    def update(self):
        if not self.exploded:
            # 向上飞行
            self.y -= self.speed
            if self.y <= self.target_y:
                self.explode()
        else:
            # 更新爆炸粒子
            new_parts = []
            for p in self.particles:
                p.update()
                if p.life > 0:
                    new_parts.append(p)
            self.particles = new_parts

    def explode(self):
        self.exploded = True
        count = random.randint(60, 120)
        for i in range(count):
            angle = math.pi * 2 * i / count + random.uniform(-0.2, 0.2)
            speed = random.uniform(1.5, 4.5)
            life = random.randint(30, 65)
            particle = Particle(self.x, self.y, speed, angle, self.color, random.uniform(2, 4), life)
            self.particles.append(particle)

    def draw(self):
        if not self.exploded:
            # 绘制上升光点
            canvas.create_oval(self.x - 2, self.y - 2, self.x + 2, self.y + 2, fill="#fff")
        else:
            for p in self.particles:
                p.draw()


fireworks = []

def loop():
    canvas.delete("all")
    # 随机生成新烟花
    if random.random() < 0.06:
        fireworks.append(FireWork())

    # 更新所有烟花
    alive_fireworks = []
    for fw in fireworks:
        fw.update()
        fw.draw()
        # 存在粒子则保留
        if not fw.exploded or len(fw.particles) > 0:
            alive_fireworks.append(fw)
    fireworks[:] = alive_fireworks

    root.after(16, loop)  # ~60帧

loop()
root.mainloop()