import pygame
import math
import random
import colorsys
from collections import deque

# 初始化Pygame
pygame.init()
WIDTH, HEIGHT = 1000, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("🎨 量子宇宙图形系统 🚀")
clock = pygame.time.Clock()

# 颜色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 50, 50)
GREEN = (50, 255, 100)
BLUE = (50, 150, 255)
CYAN = (0, 200, 255)
YELLOW = (255, 255, 50)
PURPLE = (180, 70, 255)
ORANGE = (255, 150, 50)
PINK = (255, 100, 150)

def hsv_to_rgb(h, s=1.0, v=1.0):
    rgb = colorsys.hsv_to_rgb(h, s, v)
    return (int(rgb[0]*255), int(rgb[1]*255), int(rgb[2]*255))

class Vector3:
    def __init__(self, x=0, y=0, z=0):
        self.x, self.y, self.z = float(x), float(y), float(z)
    
    def __add__(self, other):
        return Vector3(self.x + other.x, self.y + other.y, self.z + other.z)
    
    def __sub__(self, other):
        return Vector3(self.x - other.x, self.y - other.y, self.z - other.z)
    
    def __mul__(self, scalar):
        return Vector3(self.x * scalar, self.y * scalar, self.z * scalar)
    
    def length(self):
        return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
    
    def normalized(self):
        l = self.length()
        if l > 0:
            return Vector3(self.x/l, self.y/l, self.z/l)
        return Vector3(0, 0, 0)
    
    def rotate_y(self, angle):
        cos_a, sin_a = math.cos(angle), math.sin(angle)
        return Vector3(
            self.x * cos_a + self.z * sin_a,
            self.y,
            -self.x * sin_a + self.z * cos_a
        )

class Camera3D:
    def __init__(self, pos=None, target=None):
        self.pos = pos if pos else Vector3(0, 0, -15)
        self.target = target if target else Vector3(0, 0, 0)
        
    def project(self, point):
        # 简单透视投影
        rel_x = point.x - self.pos.x
        rel_y = point.y - self.pos.y
        rel_z = point.z - self.pos.z
        
        if rel_z <= 0:
            return None
        
        factor = 500 / (rel_z + 0.001)
        screen_x = WIDTH/2 + rel_x * factor
        screen_y = HEIGHT/2 - rel_y * factor
        
        return (int(screen_x), int(screen_y), rel_z)

class Particle:
    def __init__(self, pos=None, color=None, size=2.0):
        self.pos = pos if pos else Vector3(
            random.uniform(-5, 5),
            random.uniform(-5, 5),
            random.uniform(0, 10)
        )
        self.color = color if color else hsv_to_rgb(random.random())
        self.size = size
        self.vel = Vector3(
            random.uniform(-0.02, 0.02),
            random.uniform(-0.02, 0.02),
            random.uniform(-0.01, 0.01)
        )
    
    def update(self):
        self.pos = self.pos + self.vel
        return -20 < self.pos.z < 20
    
    def draw(self, surface, camera):
        proj = camera.project(self.pos)
        if proj:
            x, y, depth = proj
            if 0 <= x < WIDTH and 0 <= y < HEIGHT:
                size = max(1, int(self.size * 100 / (depth + 1)))
                pygame.draw.circle(surface, self.color, (x, y), size)

class Galaxy:
    def __init__(self, num_stars=200):
        self.stars = []
        self.rotation = 0
        
        for _ in range(num_stars):
            angle = random.uniform(0, 2*math.pi)
            radius = random.uniform(2, 10)
            height = random.uniform(-2, 2)
            
            x = math.cos(angle) * radius
            z = math.sin(angle) * radius
            
            self.stars.append({
                'pos': Vector3(x, height, z),
                'color': hsv_to_rgb(0.7 + random.uniform(-0.1, 0.1), 0.5, 0.8),
                'size': random.uniform(0.5, 2.0)
            })
    
    def update(self):
        self.rotation += 0.01
        for star in self.stars:
            star['pos'] = star['pos'].rotate_y(0.005)
    
    def draw(self, surface, camera):
        for star in self.stars:
            proj = camera.project(star['pos'])
            if proj:
                x, y, depth = proj
                if 0 <= x < WIDTH and 0 <= y < HEIGHT:
                    size = max(1, int(star['size'] * 50 / (depth + 1)))
                    pygame.draw.circle(surface, star['color'], (x, y), size)

class Vortex:
    def __init__(self, num_particles=100):
        self.particles = []
        
        for i in range(num_particles):
            angle = 2 * math.pi * i / num_particles
            radius = random.uniform(1, 6)
            height = random.uniform(-3, 3)
            
            x = math.cos(angle) * radius
            z = math.sin(angle) * radius
            
            self.particles.append({
                'pos': Vector3(x, height, z),
                'angle': angle,
                'radius': radius,
                'color': hsv_to_rgb(0.6 + radius*0.05, 0.8, 0.9)
            })
    
    def update(self):
        for p in self.particles:
            p['angle'] += 0.05 / (p['radius'] + 0.5)
            p['pos'].x = math.cos(p['angle']) * p['radius']
            p['pos'].z = math.sin(p['angle']) * p['radius']
    
    def draw(self, surface, camera):
        for p in self.particles:
            proj = camera.project(p['pos'])
            if proj:
                x, y, depth = proj
                if 0 <= x < WIDTH and 0 <= y < HEIGHT:
                    size = max(2, int(3 * 50 / (depth + 1)))
                    pygame.draw.circle(surface, p['color'], (x, y), size)

class Game:
    def __init__(self):
        self.mode = 0
        self.camera = Camera3D()
        self.galaxy = Galaxy()
        self.vortex = Vortex()
        self.particles = []
        self.rotation = 0
        
        # UI字体
        self.font = pygame.font.Font(None, 24)
        self.title_font = pygame.font.Font(None, 36)
    
    def update(self):
        self.rotation += 0.5
        
        if self.mode == 0:
            self.galaxy.update()
        elif self.mode == 1:
            self.vortex.update()
        
        # 更新粒子
        self.particles = [p for p in self.particles if p.update()]
        
        # 添加新粒子
        if len(self.particles) < 100:
            self.particles.append(Particle())
    
    def draw(self, surface):
        surface.fill(BLACK)
        
        # 绘制背景星星
        for _ in range(50):
            x = random.randint(0, WIDTH)
            y = random.randint(0, HEIGHT)
            size = random.randint(1, 3)
            pygame.draw.circle(surface, WHITE, (x, y), size)
        
        # 绘制3D对象
        if self.mode == 0:
            self.galaxy.draw(surface, self.camera)
        elif self.mode == 1:
            self.vortex.draw(surface, self.camera)
        
        # 绘制粒子
        for particle in self.particles:
            particle.draw(surface, self.camera)
        
        # 绘制UI
        self.draw_ui(surface)
    
    def draw_ui(self, surface):
        # 标题
        title = self.title_font.render("🎨 量子宇宙图形系统 🚀", True, CYAN)
        surface.blit(title, (WIDTH//2 - title.get_width()//2, 20))
        
        # 模式
        modes = ["🌌 旋转星系", "🌀 宇宙漩涡", "✨ 粒子系统"]
        mode_text = self.font.render(f"模式: {modes[self.mode]}", True, YELLOW)
        surface.blit(mode_text, (20, 80))
        
        # 控制说明
        controls = [
            "1-3: 切换模式",
            "WASD: 移动相机",
            "鼠标: 旋转视角",
            "ESC: 退出"
        ]
        
        for i, text in enumerate(controls):
            control_text = self.font.render(text, True, WHITE)
            surface.blit(control_text, (WIDTH - 200, 80 + i*30))
        
        # 粒子数量
        particle_text = self.font.render(f"粒子数: {len(self.particles)}", True, GREEN)
        surface.blit(particle_text, (20, 120))
    
    def handle_event(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_1:
                self.mode = 0
            elif event.key == pygame.K_2:
                self.mode = 1
            elif event.key == pygame.K_3:
                self.mode = 2
            elif event.key == pygame.K_ESCAPE:
                return False
            
            # 相机控制
            elif event.key == pygame.K_w:
                self.camera.pos.z += 1
            elif event.key == pygame.K_s:
                self.camera.pos.z -= 1
            elif event.key == pygame.K_a:
                self.camera.pos.x -= 1
            elif event.key == pygame.K_d:
                self.camera.pos.x += 1
        
        return True

def main():
    game = Game()
    running = True
    
    print("=" * 50)
    print("🎨 量子宇宙图形系统 🚀")
    print("=" * 50)
    print("控制说明:")
    print("1: 星系模式")
    print("2: 漩涡模式")
    print("3: 粒子模式")
    print("WASD: 移动相机")
    print("ESC: 退出")
    print("=" * 50)
    
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                running = game.handle_event(event)
        
        game.update()
        game.draw(screen)
        pygame.display.flip()
        clock.tick(60)
    
    pygame.quit()

if __name__ == "__main__":
    main()