import pygame
import sys
import random
import math
import os
from pygame.locals import *

# 初始化pygame
pygame.init()

# 设置窗口尺寸
WIDTH, HEIGHT = 1000, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("动漫风格烟花模拟 - 元宝制作")

# 颜色定义
BLACK = (0, 0, 0)
DARK_BLUE = (5, 5, 30)
WHITE = (255, 255, 255)
COLORS = [
    (255, 50, 50),    # 红色
    (50, 255, 50),    # 绿色
    (50, 150, 255),   # 蓝色
    (255, 255, 50),   # 黄色
    (255, 50, 255),   # 紫色
    (50, 255, 255),   # 青色
    (255, 150, 50),   # 橙色
    (255, 200, 100)   # 浅橙色
]

# 尝试加载中文字体


def load_font(font_name, size):
    try:
        # 尝试加载系统字体
        font = pygame.font.SysFont(font_name, size)
        # 测试中文字符
        test_surface = font.render("测试", True, WHITE)
        if test_surface.get_width() > 0:
            return font
    except:
        pass

    # 如果系统字体失败，尝试默认字体
    try:
        return pygame.font.Font(None, size)
    except:
        # 最后尝试使用基本字体
        return pygame.font.Font(pygame.font.get_default_font(), size)


# 加载字体
font_28 = load_font(['microsoftyahei', 'simhei', 'simsun', 'arial'], 28)
font_36 = load_font(['microsoftyahei', 'simhei', 'simsun', 'arial'], 36)
font_48 = load_font(['microsoftyahei', 'simhei', 'simsun', 'arial'], 48)

# 背景星星类


class Star:
    def __init__(self):
        self.x = random.randint(0, WIDTH)
        self.y = random.randint(0, HEIGHT)
        self.size = random.uniform(0.1, 1.5)
        self.brightness = random.randint(150, 255)
        self.twinkle_speed = random.uniform(0.5, 2.0)
        self.twinkle_offset = random.uniform(0, 2 * math.pi)

    def update(self, time):
        # 星星闪烁效果
        self.brightness = 150 + \
            int(105 * math.sin(time * self.twinkle_speed + self.twinkle_offset))

    def draw(self, surface):
        color = (self.brightness, self.brightness, self.brightness)
        pygame.draw.circle(surface, color, (int(self.x),
                           int(self.y)), int(self.size))

# 烟花粒子类


class Particle:
    def __init__(self, x, y, color, angle, speed, size=2.5):
        self.x = x
        self.y = y
        self.color = color
        self.angle = angle
        self.speed = speed
        self.size = size
        self.vx = math.cos(angle) * speed
        self.vy = math.sin(angle) * speed
        self.gravity = 0.1
        self.resistance = 0.99
        self.life = 100
        self.trail = []
        self.max_trail_length = 8

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += self.gravity
        self.vx *= self.resistance
        self.vy *= self.resistance
        self.life -= 1

        # 记录轨迹
        self.trail.append((self.x, self.y))
        if len(self.trail) > self.max_trail_length:
            self.trail.pop(0)

    def is_alive(self):
        return self.life > 0

    def draw(self, surface):
        # 绘制粒子轨迹
        for i, (trail_x, trail_y) in enumerate(self.trail):
            alpha = int(255 * (i / len(self.trail)) * 0.7)
            if alpha > 0:
                trail_color = (self.color[0], self.color[1], self.color[2])
                trail_size = int(self.size * (i / len(self.trail)))
                if trail_size > 0:
                    pygame.draw.circle(surface, trail_color,
                                       (int(trail_x), int(trail_y)), trail_size)

        # 绘制粒子主体
        pygame.draw.circle(surface, self.color,
                           (int(self.x), int(self.y)), int(self.size))

        # 绘制粒子光晕
        glow_radius = int(self.size * 2.5)
        glow_surface = pygame.Surface(
            (glow_radius * 2, glow_radius * 2), pygame.SRCALPHA)
        pygame.draw.circle(glow_surface, (*self.color, 80),
                           (glow_radius, glow_radius), glow_radius)
        surface.blit(glow_surface, (int(self.x - glow_radius),
                     int(self.y - glow_radius)), special_flags=BLEND_ALPHA_SDL2)

# 烟花类


class Firework:
    def __init__(self, x=None, y=None):
        self.x = x if x else random.randint(100, WIDTH - 100)
        self.y = y if y else HEIGHT
        self.target_y = random.randint(50, HEIGHT // 2)
        self.speed = random.uniform(3, 6)
        self.color = random.choice(COLORS)
        self.particles = []
        self.exploded = False
        self.trail = []

    def update(self):
        if not self.exploded:
            # 上升阶段
            self.y -= self.speed
            self.trail.append((self.x, self.y))
            if len(self.trail) > 15:
                self.trail.pop(0)

            # 到达目标高度时爆炸
            if self.y <= self.target_y:
                self.explode()
        else:
            # 更新所有粒子
            for particle in self.particles[:]:
                particle.update()
                if not particle.is_alive():
                    self.particles.remove(particle)

    def explode(self):
        self.exploded = True
        # 生成爆炸粒子
        particle_count = random.randint(80, 150)
        for _ in range(particle_count):
            angle = random.uniform(0, 2 * math.pi)
            speed = random.uniform(1, 5)
            size = random.uniform(1.5, 3.5)
            particle = Particle(self.x, self.y, self.color, angle, speed, size)
            self.particles.append(particle)

        # 添加一些特殊效果粒子
        for _ in range(20):
            angle = random.uniform(0, 2 * math.pi)
            speed = random.uniform(6, 10)
            size = random.uniform(3, 5)
            # 使用亮色作为特殊效果粒子
            bright_color = (min(255, self.color[0] + 100),
                            min(255, self.color[1] + 100),
                            min(255, self.color[2] + 100))
            particle = Particle(
                self.x, self.y, bright_color, angle, speed, size)
            self.particles.append(particle)

    def is_done(self):
        return self.exploded and len(self.particles) == 0

    def draw(self, surface):
        if not self.exploded:
            # 绘制上升轨迹
            for i, (trail_x, trail_y) in enumerate(self.trail):
                alpha = int(255 * (i / len(self.trail)) * 0.5)
                if alpha > 0:
                    trail_color = (*self.color, alpha)
                    trail_size = 2 * (i / len(self.trail))
                    pygame.draw.circle(surface, trail_color, (int(
                        trail_x), int(trail_y)), int(trail_size))

            # 绘制上升的火花
            pygame.draw.circle(surface, self.color,
                               (int(self.x), int(self.y)), 3)

            # 绘制上升火花的光晕
            glow_radius = 8
            glow_surface = pygame.Surface(
                (glow_radius * 2, glow_radius * 2), pygame.SRCALPHA)
            pygame.draw.circle(glow_surface, (*self.color, 120),
                               (glow_radius, glow_radius), glow_radius)
            surface.blit(glow_surface, (int(self.x - glow_radius),
                         int(self.y - glow_radius)), special_flags=BLEND_ALPHA_SDL2)
        else:
            # 绘制所有粒子
            for particle in self.particles:
                particle.draw(surface)


# 创建背景星星
stars = [Star() for _ in range(150)]

# 烟花列表
fireworks = []

# 计时器
clock = pygame.time.Clock()
time_passed = 0
firework_timer = 0
auto_firework_interval = 1000  # 自动发射烟花的间隔（毫秒）

# 渲染文本函数（处理可能的编码问题）


def render_text(font, text, color, antialias=True):
    try:
        return font.render(text, antialias, color)
    except:
        # 如果渲染失败，尝试使用ASCII回退
        try:
            ascii_text = text.encode('ascii', 'ignore').decode('ascii')
            return font.render(ascii_text, antialias, color)
        except:
            # 最后尝试空字符串
            return font.render("", antialias, color)

# 绘制文本到屏幕


def draw_text(surface, font, text, color, x, y, center_x=False, center_y=False):
    text_surface = render_text(font, text, color)
    if text_surface.get_width() > 0:
        text_rect = text_surface.get_rect()
        if center_x:
            text_rect.centerx = x
        else:
            text_rect.x = x

        if center_y:
            text_rect.centery = y
        else:
            text_rect.y = y

        surface.blit(text_surface, text_rect)
        return text_rect
    return pygame.Rect(x, y, 0, 0)


# 主游戏循环
running = True
while running:
    current_time = pygame.time.get_ticks()
    dt = clock.tick(60)
    time_passed += dt / 1000.0

    # 处理事件
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
            elif event.key == K_SPACE:
                # 空格键发射多个烟花
                for _ in range(3):
                    fireworks.append(Firework())
        elif event.type == MOUSEBUTTONDOWN:
            # 鼠标点击发射烟花
            if event.button == 1:  # 左键
                fireworks.append(Firework(event.pos[0], HEIGHT))
            elif event.button == 3:  # 右键
                for _ in range(5):
                    fireworks.append(
                        Firework(event.pos[0] + random.randint(-50, 50), HEIGHT))

    # 自动发射烟花
    firework_timer += dt
    if firework_timer >= auto_firework_interval:
        firework_timer = 0
        auto_firework_interval = random.randint(800, 2000)
        # 随机发射1-3个烟花
        for _ in range(random.randint(1, 3)):
            fireworks.append(Firework())

    # 更新星星
    for star in stars:
        star.update(time_passed)

    # 更新烟花
    for firework in fireworks[:]:
        firework.update()
        if firework.is_done():
            fireworks.remove(firework)

    # 绘制背景
    screen.fill(DARK_BLUE)

    # 绘制背景星星
    for star in stars:
        star.draw(screen)

    # 绘制远处的城市轮廓（简化版）
    pygame.draw.rect(screen, (20, 20, 40), (0, HEIGHT - 100, WIDTH, 100))
    for i in range(20):
        building_x = i * 50
        building_width = random.randint(30, 60)
        building_height = random.randint(20, 80)
        building_color = (random.randint(10, 30), random.randint(
            10, 30), random.randint(20, 40))
        pygame.draw.rect(screen, building_color,
                         (building_x, HEIGHT - 100 - building_height, building_width, building_height))

    # 绘制烟花
    for firework in fireworks:
        firework.draw(screen)

    # 绘制UI元素
    draw_text(screen, font_48, "动漫风格烟花模拟", (255, 255, 200),
              WIDTH // 2, 20, center_x=True)

    # 操作说明
    instructions = [
        "操作说明:",
        "左键点击: 发射单个烟花",
        "右键点击: 发射多个烟花",
        "空格键: 发射一组烟花",
        "ESC键: 退出程序"
    ]

    for i, line in enumerate(instructions):
        draw_text(screen, font_28, line, (220, 220, 255), 20, 20 + i * 30)

    # 显示烟花数量
    draw_text(screen, font_28, f"当前烟花数量: {len(fireworks)}",
              (200, 255, 200), WIDTH - 20, HEIGHT - 40, center_x=False)

    # 显示帧率
    fps_text = f"帧率: {int(clock.get_fps())}"
    draw_text(screen, font_28, fps_text, (200, 200, 255),
              WIDTH - 20, 20, center_x=False)

    # 绘制底部提示
    draw_text(screen, font_36, "观赏美丽的动漫烟花绽放吧！", (255, 200, 100),
              WIDTH // 2, HEIGHT - 80, center_x=True)

    # 版权信息
    draw_text(screen, font_28, "由元宝制作 (腾讯出品)", (180, 180, 220),
              WIDTH // 2, HEIGHT - 30, center_x=True)

    # 更新屏幕
    pygame.display.flip()

# 退出游戏
pygame.quit()
sys.exit()
