"""
动态烟花游戏 - 自动+手动模式
开发者: 卢思成
学校: 东台市第一小学
班级: 六（10）班
学号: 19号
版本: 1.0
"""

import pygame
import random
import math
import sys

# 初始化pygame
pygame.init()

# 屏幕设置
WIDTH, HEIGHT = 1200, 780
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("🎆 动态烟花游戏 - 卢思成制作 🎆")
clock = pygame.time.Clock()

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
NAVY = (5, 5, 30)
COLORS = [
    (255, 50, 50),     # 红色
    (50, 255, 50),     # 绿色
    (50, 130, 255),    # 蓝色
    (255, 240, 50),    # 黄色
    (255, 50, 210),    # 紫色
    (50, 245, 225),    # 青色
    (252, 186, 54),    # 橙色
    (219, 112, 247),   # 粉色
    (173, 254, 51),    # 荧光绿
    (253, 94, 142),    # 玫瑰红
]

class Particle:
    """单个烟花粒子"""
    def __init__(self, x, y, color, vx, vy, size=3, gravity=0.08, fade=0.985, life=120):
        self.x = x
        self.y = y
        self.color = color
        self.vx = vx
        self.vy = vy
        self.size = size
        self.origin_size = size
        self.gravity = gravity
        self.fade = fade
        self.life = life
        self.max_life = life
        self.trail = []
        self.alive = True
        
    def update(self):
        if not self.alive:
            return
            
        # 物理更新
        self.vy += self.gravity
        self.vx *= self.fade
        self.vy *= self.fade
        self.x += self.vx
        self.y += self.vy
        
        # 记录轨迹
        self.trail.append((int(self.x), int(self.y)))
        if len(self.trail) > 8:
            self.trail.pop(0)
        
        # 生命衰减
        self.life -= 1
        progress = 1 - (self.life / self.max_life)
        self.size = self.origin_size * (1 - progress * 0.7)
        
        if self.life <= 0 or self.size <= 0.3:
            self.alive = False
    
    def draw(self, surface):
        if not self.alive:
            return
            
        # 绘制轨迹
        if len(self.trail) > 1:
            for i in range(1, len(self.trail)):
                alpha = int(180 * (i / len(self.trail)))
                thickness = max(1, int(self.size * 0.6 * (i / len(self.trail))))
                pygame.draw.line(surface, (*self.color, alpha), 
                               self.trail[i-1], self.trail[i], thickness)
        
        # 绘制粒子本体
        if self.size > 0.5:
            pygame.draw.circle(surface, self.color, 
                             (int(self.x), int(self.y)), int(self.size))
            
            # 发光效果
            glow_size = int(self.size * 3)
            if glow_size > 1:
                glow_surf = pygame.Surface((glow_size*2, glow_size*2), pygame.SRCALPHA)
                alpha = int(60 * (self.life / self.max_life))
                pygame.draw.circle(glow_surf, (*self.color, alpha), 
                                 (glow_size, glow_size), glow_size)
                surface.blit(glow_surf, (int(self.x-glow_size), int(self.y-glow_size)))

class Spark(Particle):
    """火花特效粒子"""
    def __init__(self, x, y, color):
        angle = random.uniform(0, math.pi*2)
        speed = random.uniform(3, 8)
        super().__init__(x, y, color, 
                        math.cos(angle)*speed, 
                        math.sin(angle)*speed,
                        size=random.uniform(1, 2.5),
                        gravity=0.15,
                        fade=0.92,
                        life=random.randint(15, 30))

class Firework:
    """烟花类"""
    def __init__(self, x, y, color=None, particles_count=None):
        self.x = x
        self.y = HEIGHT
        self.target_x = x
        self.target_y = y
        self.color = color if color else random.choice(COLORS)
        self.vy = -random.uniform(8, 13)
        self.vx = random.uniform(-0.5, 0.5)
        self.gravity = 0.22
        self.exploded = False
        self.particles = []
        self.trail = []
        self.particles_count = particles_count if particles_count else random.randint(60, 110)
        self.explosion_radius = random.uniform(80, 150)
        self.flash_alpha = 0
        
    def update(self):
        if not self.exploded:
            # 上升阶段
            self.vy += self.gravity
            self.x += self.vx
            self.y += self.vy
            
            # 记录轨迹
            self.trail.append((int(self.x), int(self.y)))
            if len(self.trail) > 25:
                self.trail.pop(0)
            
            # 到达目标高度或开始下落时爆炸
            if self.vy >= 0 or self.y <= self.target_y:
                self.explode()
        else:
            # 更新所有粒子
            for particle in self.particles[:]:
                particle.update()
                if not particle.alive:
                    self.particles.remove(particle)
            
            # 闪光衰减
            if self.flash_alpha > 0:
                self.flash_alpha -= 15
    
    def explode(self):
        self.exploded = True
        self.flash_alpha = 200
        
        # 主爆炸粒子
        for _ in range(self.particles_count):
            angle = random.uniform(0, math.pi * 2)
            speed = random.uniform(2, 7) * (self.explosion_radius / 115)
            vx = math.cos(angle) * speed
            vy = math.sin(angle) * speed
            
            # 颜色微调
            color = tuple(max(0, min(255, c + random.randint(-30, 30))) 
                         for c in self.color)
            
            size = random.uniform(2, 5)
            gravity = random.uniform(0.065, 0.145)
            fade = random.uniform(0.975, 0.993)
            life = random.randint(60, 170)
            
            self.particles.append(Particle(
                self.target_x, self.target_y, color, vx, vy, 
                size, gravity, fade, life
            ))
        
        # 额外火花
        for _ in range(self.particles_count // 3):
            spark_color = tuple(min(255, c + 60) for c in self.color)
            self.particles.append(Spark(self.target_x, self.target_y, spark_color))
        
        # 中心爆裂
        for _ in range(10):
            angle = random.uniform(0, math.pi*2)
            speed = random.uniform(1, 3)
            self.particles.append(Particle(
                self.target_x, self.target_y, WHITE,
                math.cos(angle)*speed, math.sin(angle)*speed,
                size=1.5, gravity=0.035, fade=0.995, life=40
            ))
    
    def draw(self, surface):
        if not self.exploded:
            # 绘制上升轨迹
            if len(self.trail) > 1:
                for i in range(1, len(self.trail)):
                    alpha = int(180 * (i / len(self.trail)))
                    pygame.draw.line(surface, (*self.color, alpha), 
                                   self.trail[i-1], self.trail[i], 
                                   max(1, int(2 * i / len(self.trail))))
            
            # 绘制烟花弹
            pygame.draw.circle(surface, self.color, 
                             (int(self.x), int(self.y)), 4)
            pygame.draw.circle(surface, WHITE, 
                             (int(self.x), int(self.y)), 2)
        else:
            # 绘制闪光
            if self.flash_alpha > 0:
                flash_surf = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
                radius = 60
                pygame.draw.circle(flash_surf, (*self.color, self.flash_alpha), 
                                 (int(self.target_x), int(self.target_y)), radius)
                surface.blit(flash_surf, (0, 0))
            
            # 绘制所有粒子
            for particle in self.particles:
                particle.draw(surface)
    
    @property
    def alive(self):
        if not self.exploded:
            return self.y < HEIGHT + 50
        return len(self.particles) > 0

class Star:
    """星星背景"""
    def __init__(self):
        self.x = random.randint(0, WIDTH)
        self.y = random.randint(0, HEIGHT)
        self.size = random.uniform(0.3, 2)
        self.brightness = random.uniform(0.3, 1)
        self.twinkle_speed = random.uniform(0.015, 0.045)
        self.twinkle_dir = 1
        
    def update(self):
        self.brightness += self.twinkle_speed * self.twinkle_dir
        if self.brightness >= 1:
            self.brightness = 1
            self.twinkle_dir = -1
        elif self.brightness <= 0.2:
            self.brightness = 0.2
            self.twinkle_dir = 1
    
    def draw(self, surface):
        val = int(255 * self.brightness)
        pygame.draw.circle(surface, (val, val, val), 
                         (int(self.x), int(self.y)), self.size)

class Game:
    """游戏主类"""
    def __init__(self):
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        self.clock = pygame.time.Clock()
        self.running = True
        
        # 游戏对象
        self.fireworks = []
        self.stars = [Star() for _ in range(150)]
        
        # 自动模式
        self.auto_mode = True
        self.auto_timer = 0
        self.auto_delay = random.randint(400, 1200)
        
        # UI
        self.font_large = pygame.font.Font(None, 52)
        self.font_mid = pygame.font.Font(None, 32)
        self.font_small = pygame.font.Font(None, 26)
        self.show_help = True
        self.help_timer = 0
        
        # 统计
        self.total_fireworks = 0
        self.max_particles = 0
        
        # 背景渐变
        self.bg_surface = self.create_background()
        
    def create_background(self):
        """创建渐变背景"""
        surf = pygame.Surface((WIDTH, HEIGHT))
        for y in range(HEIGHT):
            ratio = y / HEIGHT
            r = int(5 + 10 * ratio)
            g = int(5 + 15 * ratio)
            b = int(30 + 50 * ratio)
            pygame.draw.line(surf, (r, g, b), (0, y), (WIDTH, y))
        return surf
    
    def add_firework(self, x=None, y=None, count=1, color=None):
        """添加烟花"""
        for _ in range(count):
            fx = x if x else random.randint(100, WIDTH-100)
            fy = y if y else random.randint(80, HEIGHT//2 - 20)
            fc = color if color else random.choice(COLORS)
            self.fireworks.append(Firework(fx, fy, fc))
            self.total_fireworks += 1
    
    def handle_events(self):
        """处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.running = False
                elif event.key == pygame.K_SPACE:
                    # 空格：随机发射5个烟花
                    self.add_firework(count=5)
                elif event.key == pygame.K_a:
                    # A键：切换自动模式
                    self.auto_mode = not self.auto_mode
                    self.auto_timer = 0
                elif event.key == pygame.K_c:
                    # C键：清除所有烟花
                    self.fireworks.clear()
                elif event.key == pygame.K_h:
                    # H键：切换帮助显示
                    self.show_help = not self.show_help
                elif event.key == pygame.K_RETURN:
                    # 回车：发射大型烟花组
                    for _ in range(12):
                        self.add_firework(
                            random.randint(50, WIDTH-50),
                            random.randint(80, HEIGHT//2)
                        )
                elif event.key == pygame.K_1:
                    # 数字键：发射特定颜色
                    if 0 <= 0 < len(COLORS):
                        self.add_firework(color=COLORS[0], count=3)
                elif event.key == pygame.K_2:
                    if 1 < len(COLORS):
                        self.add_firework(color=COLORS[1], count=3)
                elif event.key == pygame.K_3:
                    if 2 < len(COLORS):
                        self.add_firework(color=COLORS[2], count=3)
                elif event.key == pygame.K_4:
                    if 3 < len(COLORS):
                        self.add_firework(color=COLORS[3], count=3)
                elif event.key == pygame.K_5:
                    if 4 < len(COLORS):
                        self.add_firework(color=COLORS[4], count=3)
            
            elif event.type == pygame.MOUSEBUTTONDOWN:
                x, y = event.pos
                if event.button == 1:  # 左键
                    self.add_firework(x, y, count=3)
                elif event.button == 3:  # 右键
                    self.add_firework(x, y, count=6)
    
    def update(self):
        """更新游戏状态"""
        current_time = pygame.time.get_ticks()
        
        # 更新星星
        for star in self.stars:
            star.update()
        
        # 自动模式
        if self.auto_mode:
            if current_time - self.auto_timer > self.auto_delay:
                self.add_firework(count=random.randint(1, 3))
                self.auto_timer = current_time
                self.auto_delay = random.randint(300, 1500)
        
        # 更新烟花
        for firework in self.fireworks[:]:
            firework.update()
            if not firework.alive:
                self.fireworks.remove(firework)
        
        # 统计最大粒子数
        total_particles = sum(len(f.particles) for f in self.fireworks if f.exploded)
        self.max_particles = max(self.max_particles, total_particles)
        
        # 帮助显示定时
        if self.show_help:
            self.help_timer += 1
            if self.help_timer > 480:  # 8秒后自动隐藏
                self.show_help = False
    
    def draw(self):
        """绘制画面"""
        # 绘制背景
        self.screen.blit(self.bg_surface, (0, 0))
        
        # 绘制星星
        for star in self.stars:
            star.draw(self.screen)
        
        # 绘制烟花
        for firework in self.fireworks:
            firework.draw(self.screen)
        
        # 绘制UI
        self.draw_ui()
        
        pygame.display.flip()
    
    def draw_ui(self):
        """绘制UI"""
        # 标题
        title = self.font_large.render("🎆 动态烟花秀 🎆", True, WHITE)
        title_shadow = self.font_large.render("🎆 动态烟花秀 🎆", True, (100, 100, 100))
        self.screen.blit(title_shadow, (WIDTH//2 - title.get_width()//2 + 2, 17))
        self.screen.blit(title, (WIDTH//2 - title.get_width()//2, 15))
        
        # 状态信息
        mode_text = "🔄 自动模式" if self.auto_mode else "✋ 手动模式"
        info = f"{mode_text} | 烟花: {len(self.fireworks)} | 总计: {self.total_fireworks} | 峰值粒子: {self.max_particles}"
        info_surf = self.font_small.render(info, True, (200, 200, 200))
        self.screen.blit(info_surf, (20, HEIGHT - 38))
        
        # 颜色指示器
        for i, color in enumerate(COLORS):
            x = 20 + i * 46
            y = HEIGHT - 68
            pygame.draw.circle(self.screen, color, (x + 10, y + 10), 8)
            pygame.draw.circle(self.screen, WHITE, (x + 10, y + 10), 8, 1)
            key_text = self.font_small.render(str(i+1), True, WHITE)
            self.screen.blit(key_text, (x + 5, y + 15))
        
        # 帮助信息
        if self.show_help:
            help_lines = [
                "🎮 控制说明:",
                "🖱️ 左键点击: 发射3个烟花",
                "🖱️ 右键点击: 发射6个烟花",
                "⌨️ 空格键: 随机发射5个烟花",
                "⌨️ Enter键: 发射12个大型烟花",
                "⌨️ 1-5键: 发射对应颜色的烟花",
                "⌨️ A键: 切换自动/手动模式",
                "⌨️ C键: 清除所有烟花",
                "⌨️ H键: 显示/隐藏帮助",
                "⌨️ ESC键: 退出游戏"
            ]
            
            help_surf = pygame.Surface((280, 320), pygame.SRCALPHA)
            help_surf.fill((0, 0, 0, 190))
            self.screen.blit(help_surf, (WIDTH - 300, 62))
            
            for i, line in enumerate(help_lines):
                color = WHITE if i == 0 else (200, 200, 200)
                text = self.font_small.render(line, True, color)
                self.screen.blit(text, (WIDTH - 290, 68 + i * 28))
    
    def run(self):
        """运行游戏"""
        print("""
        ╔══════════════════════════════════════════╗
        ║       🎆 动态烟花游戏 🎆                 ║
        ║  开发者: 卢思成                          ║
        ║  学校: 东台市第一小学                   ║
        ║  班级: 六（10）班                      ║
        ║  学号: 19号                            ║
        ╠══════════════════════════════════════════╣
        ║  控制说明:                              ║
        ║  🖱️ 左键: 发射3个烟花                   ║
        ║  🖱️ 右键: 发射6个烟花                   ║
        ║  ⌨️ 空格: 随机5个烟花                    ║
        ║  ⌨️ Enter: 12个大型烟花                  ║
        ║  ⌨️ 1-5: 对应颜色烟花                    ║
        ║  ⌨️ A: 切换自动/手动                     ║
        ║  ⌨️ C: 清除烟花                          ║
        ║  ⌨️ H: 帮助开关                          ║
        ║  ⌨️ ESC: 退出                            ║
        ╚══════════════════════════════════════════╝
        """)
        
        while self.running:
            self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(60)
        
        pygame.quit()
        sys.exit()

# 运行游戏
if __name__ == "__main__":
    game = Game()
    game.run()