
import tkinter as tk
import random
import math
import time


class Particle:
    """粒子类，代表烟花中的每一个火花"""

    def __init__(self, canvas, x, y, color, velocity, lifespan=100):
        self.canvas = canvas
        self.x = x
        self.y = y
        self.color = color
        # 速度分解
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.lifespan = lifespan
        self.age = 0
        self.size = random.randint(2, 4)
        self.id = self.canvas.create_oval(
            x, y, x + self.size, y + self.size, fill=color, outline='')

    def update(self):
        """更新粒子位置和状态"""
        self.age += 1
        # 重力影响
        self.vy += 0.05
        # 空气阻力
        self.vx *= 0.98
        self.vy *= 0.98

        self.x += self.vx
        self.y += self.vy

        # 移动画布上的图形
        self.canvas.coords(self.id, self.x, self.y, self.x +
                           self.size, self.y + self.size)

        # 透明度/大小模拟衰减
        if self.age > self.lifespan * 0.7:
            new_size = max(
                0, self.size * (1 - (self.age - self.lifespan * 0.7) / (self.lifespan * 0.3)))
            if new_size <= 0:
                return False
            self.canvas.coords(self.id, self.x, self.y,
                               self.x + new_size, self.y + new_size)

        return self.age < self.lifespan

    def delete(self):
        """删除粒子"""
        self.canvas.delete(self.id)


class Firework:
    """烟花类，管理一次爆炸产生的所有粒子"""

    def __init__(self, canvas, x, y):
        self.canvas = canvas
        self.particles = []
        colors = ['#FF1461', '#18FF92', '#5A87FF', '#FBF38C',
                  '#ff0000', '#00ff00', '#0000ff', '#ffff00']
        color = random.choice(colors)

        # 产生爆炸粒子
        num_particles = random.randint(30, 50)
        for _ in range(num_particles):
            angle = random.uniform(0, 2 * math.pi)
            speed = random.uniform(1, 4)
            vx = math.cos(angle) * speed
            vy = math.sin(angle) * speed
            p = Particle(canvas, x, y, color, (vx, vy),
                         lifespan=random.randint(60, 100))
            self.particles.append(p)

    def update(self):
        """更新所有粒子，返回是否还有存活粒子"""
        alive = False
        dead_particles = []
        for p in self.particles:
            if p.update():
                alive = True
            else:
                dead_particles.append(p)

        # 清理死亡粒子
        for p in dead_particles:
            p.delete()
            self.particles.remove(p)

        return alive


class FireworkApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Python 动态烟花秀")
        self.root.geometry("800x600")
        self.root.configure(bg='black')

        # 创建画布
        self.canvas = tk.Canvas(root, bg='black', highlightthickness=0)
        self.canvas.pack(fill=tk.BOTH, expand=True)

        self.fireworks = []
        self.auto_launch_timer = None

        # 绑定鼠标点击事件
        self.canvas.bind('<Button-1>', self.on_click)

        # 启动动画循环
        self.animate()

        # 自动发射定时器
        self.schedule_auto_launch()

    def on_click(self, event):
        """鼠标点击处发射烟花"""
        self.fireworks.append(Firework(self.canvas, event.x, event.y))

    def launch_random_firework(self):
        """随机位置发射烟花"""
        w = self.canvas.winfo_width()
        h = self.canvas.winfo_height()
        if w > 1 and h > 1:
            x = random.randint(50, w - 50)
            y = random.randint(50, h // 2)  # 只在上半部分爆炸
            self.fireworks.append(Firework(self.canvas, x, y))
        self.schedule_auto_launch()

    def schedule_auto_launch(self):
        """安排下一次自动发射"""
        delay = random.randint(500, 1500)  # 0.5到1.5秒随机间隔
        self.auto_launch_timer = self.root.after(
            delay, self.launch_random_firework)

    def animate(self):
        """动画主循环"""
        # 绘制半透明黑色矩形以产生拖尾效果
        self.canvas.create_rectangle(
            0, 0, 800, 600, fill='black', stipple='gray25', outline='')

        # 更新所有烟花
        dead_fireworks = []
        for fw in self.fireworks:
            if not fw.update():
                dead_fireworks.append(fw)

        # 清理完全结束的烟花对象引用（粒子已在Firework.update中清理）
        for fw in dead_fireworks:
            self.fireworks.remove(fw)

        self.root.after(16, self.animate)  # 约60FPS


if __name__ == "__main__":
    root = tk.Tk()
    app = FireworkApp(root)
    root.mainloop()
