import tkinter as tk
import random
import math

# 烟花粒子类
class Particle:
    def __init__(self, x, y, color):
        self.x = x
        self.y = y
        self.color = color
        # 随机角度（0-360度）
        self.angle = random.uniform(0, 2 * math.pi)
        # 随机速度
        self.speed = random.uniform(1, 5)
        # 重力影响（让粒子有下落效果）
        self.gravity = 0.05
        # 速度分量
        self.vx = math.cos(self.angle) * self.speed
        self.vy = math.sin(self.angle) * self.speed
        # 粒子大小
        self.size = random.randint(2, 4)
        # 透明度（用于渐变消失）
        self.alpha = 1.0
        self.alpha_decay = random.uniform(0.01, 0.03)

    def update(self):
        # 应用重力
        self.vy += self.gravity
        # 更新位置
        self.x += self.vx
        self.y += self.vy
        # 降低透明度
        self.alpha -= self.alpha_decay
        # 速度衰减（模拟空气阻力）
        self.vx *= 0.98
        self.vy *= 0.98

    def is_alive(self):
        # 判断粒子是否还存活（透明度>0）
        return self.alpha > 0

# 烟花主类
class FireworkApp:
    def __init__(self, root):
        self.root = root
        self.root.title("动态烟花效果")
        self.root.geometry("800x600")
        self.root.resizable(False, False)

        # 创建画布
        self.canvas = tk.Canvas(root, width=800, height=600, bg="black")
        self.canvas.pack(fill=tk.BOTH, expand=True)

        # 存储所有烟花粒子
        self.particles = []
        # 存储待发射的烟花（准备升空的）
        self.fireworks = []

        # 开始动画循环
        self.animate()

        # 绑定鼠标点击事件（点击画布发射烟花）
        self.canvas.bind("<Button-1>", self.launch_firework)

    def launch_firework(self, event=None):
        """发射烟花（如果没有传事件，随机位置发射）"""
        # 发射位置（鼠标点击位置或底部随机位置）
        x = event.x if event else random.randint(100, 700)
        y = event.y if event else 600
        
        # 随机烟花颜色
        colors = ["red", "blue", "green", "yellow", "purple", "orange", "white", "pink", "cyan"]
        color = random.choice(colors)
        
        # 添加到待发射列表
        self.fireworks.append({
            "x": x,
            "y": y,
            "target_y": random.randint(100, 300),  # 爆炸高度
            "color": color,
            "speed": random.uniform(3, 6)  # 上升速度
        })

    def explode(self, x, y, color):
        """烟花爆炸，生成粒子"""
        # 生成100-200个粒子
        num_particles = random.randint(100, 200)
        for _ in range(num_particles):
            self.particles.append(Particle(x, y, color))

    def animate(self):
        """动画主循环"""
        # 清除画布（保留背景）
        self.canvas.delete("all")
        
        # 更新待发射的烟花（上升阶段）
        new_fireworks = []
        for fw in self.fireworks:
            # 绘制上升的烟花芯
            self.canvas.create_oval(
                fw["x"]-2, fw["y"]-2,
                fw["x"]+2, fw["y"]+2,
                fill=fw["color"], outline=""
            )
            
            # 上升
            fw["y"] -= fw["speed"]
            
            # 到达目标高度则爆炸
            if fw["y"] <= fw["target_y"]:
                self.explode(fw["x"], fw["y"], fw["color"])
            else:
                new_fireworks.append(fw)
        self.fireworks = new_fireworks

        # 更新并绘制粒子（爆炸后）
        new_particles = []
        for p in self.particles:
            if p.is_alive():
                p.update()
                # 绘制粒子（根据透明度调整颜色）
                alpha = int(p.alpha * 255)
                # tkinter不直接支持透明度，用颜色深浅模拟
                color = self.adjust_color(p.color, p.alpha)
                self.canvas.create_oval(
                    p.x - p.size, p.y - p.size,
                    p.x + p.size, p.y + p.size,
                    fill=color, outline=""
                )
                new_particles.append(p)
        self.particles = new_particles

        # 随机自动发射烟花（每帧有10%概率）
        if random.random() < 0.1:
            self.launch_firework()

        # 定时刷新（约60帧/秒）
        self.root.after(16, self.animate)

    def adjust_color(self, color, alpha):
        """调整颜色深浅模拟透明度"""
        # 预定义颜色的RGB值
        color_rgb = {
            "red": (255, 0, 0),
            "blue": (0, 0, 255),
            "green": (0, 255, 0),
            "yellow": (255, 255, 0),
            "purple": (128, 0, 128),
            "orange": (255, 165, 0),
            "white": (255, 255, 255),
            "pink": (255, 192, 203),
            "cyan": (0, 255, 255)
        }
        if color not in color_rgb:
            return color
        
        r, g, b = color_rgb[color]
        # 根据透明度调整RGB值
        r = int(r * alpha)
        g = int(g * alpha)
        b = int(b * alpha)
        return f"#{r:02x}{g:02x}{b:02x}"

# 主程序入口
if __name__ == "__main__":
    root = tk.Tk()
    app = FireworkApp(root)
    root.mainloop()