import pygame
import random
import sys

# --- 初始化 ---
pygame.init()
pygame.font.init()

# --- 常量定义 ---
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60

# 颜色定义
COLOR_BG = (10, 10, 25)       # 深空蓝
COLOR_PLAYER = (0, 255, 255)  # 青色玩家
COLOR_ENEMY = (255, 50, 50)   # 红色敌人
COLOR_BULLET = (255, 255, 0)  # 黄色子弹
COLOR_STAR = (200, 200, 200)  # 白色星星
COLOR_TEXT = (255, 255, 255)
COLOR_PARTICLE = (255, 100, 50) # 爆炸粒子

# 游戏参数
PLAYER_SPEED = 6
BULLET_SPEED = 10
ENEMY_SPEED_BASE = 3
SHOOT_COOLDOWN = 15  # 帧数

class Particle:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.vx = random.uniform(-4, 4)
        self.vy = random.uniform(-4, 4)
        self.life = random.randint(20, 40)
        self.size = random.randint(3, 7)
        self.color = COLOR_PARTICLE

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.life -= 1
        self.size *= 0.95  # 逐渐变小
        return self.life > 0

    def draw(self, surface):
        if self.size < 1: return
        pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), int(self.size))

class Bullet:
    def __init__(self, x, y):
        self.rect = pygame.Rect(x - 2, y, 4, 12)
        self.speed = BULLET_SPEED
        self.active = True

    def update(self):
        self.rect.y -= self.speed
        if self.rect.bottom < 0:
            self.active = False

    def draw(self, surface):
        pygame.draw.rect(surface, COLOR_BULLET, self.rect)

class Enemy:
    def __init__(self, speed_multiplier=1.0):
        self.width = 40
        self.height = 40
        self.x = random.randint(self.width, SCREEN_WIDTH - self.width)
        self.y = -self.height
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
        self.speed = ENEMY_SPEED_BASE * speed_multiplier + random.uniform(0, 1)
        self.active = True
        # 简单的摆动逻辑
        self.oscillation_offset = random.randint(0, 100)

    def update(self):
        self.y += self.speed
        # 左右轻微摆动
        self.x += math.sin((self.y + self.oscillation_offset) * 0.05) * 1.5
        self.rect.topleft = (self.x, self.y)
        
        if self.y > SCREEN_HEIGHT:
            self.active = False

    def draw(self, surface):
        # 绘制敌人飞船 (倒三角形)
        points = [
            (self.rect.centerx, self.rect.bottom),
            (self.rect.left, self.rect.top),
            (self.rect.right, self.rect.top)
        ]
        pygame.draw.polygon(surface, COLOR_ENEMY, points)
        # 引擎火焰
        flame_h = random.randint(5, 10)
        pygame.draw.polygon(surface, (255, 100, 0), [
            (self.rect.centerx - 5, self.rect.bottom),
            (self.rect.centerx + 5, self.rect.bottom),
            (self.rect.centerx, self.rect.bottom + flame_h)
        ])

class Player:
    def __init__(self):
        self.width = 50
        self.height = 50
        self.x = SCREEN_WIDTH // 2
        self.y = SCREEN_HEIGHT - 80
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
        self.speed = PLAYER_SPEED
        self.cooldown = 0
        self.alive = True

    def move(self, keys):
        if not self.alive: return
        
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.x -= self.speed
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.x += self.speed
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            self.y -= self.speed
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.y += self.speed

        # 边界限制
        self.x = max(0, min(SCREEN_WIDTH - self.width, self.x))
        self.y = max(0, min(SCREEN_HEIGHT - self.height, self.y))
        self.rect.topleft = (self.x, self.y)

        if self.cooldown > 0:
            self.cooldown -= 1

    def shoot(self):
        if self.cooldown == 0 and self.alive:
            self.cooldown = SHOOT_COOLDOWN
            return Bullet(self.rect.centerx, self.rect.top)
        return None

    def draw(self, surface):
        if not self.alive: return
        # 绘制玩家飞船 (三角形)
        points = [
            (self.rect.centerx, self.rect.top),
            (self.rect.left, self.rect.bottom),
            (self.rect.right, self.rect.bottom)
        ]
        pygame.draw.polygon(surface, COLOR_PLAYER, points)
        
        # 绘制引擎尾焰
        flame_h = random.randint(10, 20)
        pygame.draw.polygon(surface, (0, 100, 255), [
            (self.rect.left + 10, self.rect.bottom),
            (self.rect.right - 10, self.rect.bottom),
            (self.rect.centerx, self.rect.bottom + flame_h)
        ])

class Star:
    def __init__(self):
        self.x = random.randint(0, SCREEN_WIDTH)
        self.y = random.randint(0, SCREEN_HEIGHT)
        self.speed = random.uniform(0.5, 2.0)
        self.size = random.randint(1, 3)
    
    def update(self):
        self.y += self.speed
        if self.y > SCREEN_HEIGHT:
            self.y = 0
            self.x = random.randint(0, SCREEN_WIDTH)
    
    def draw(self, surface):
        pygame.draw.circle(surface, COLOR_STAR, (self.x, int(self.y)), self.size)

def draw_text(surface, text, size, x, y, color=COLOR_TEXT, center=True):
    font = pygame.font.SysFont('Arial', size, bold=True)
    render = font.render(text, True, color)
    rect = render.get_rect()
    if center:
        rect.center = (x, y)
    else:
        rect.topleft = (x, y)
    surface.blit(render, rect)

# 需要导入 math 用于敌人摆动
import math

def main():
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("Python 太空射击战")
    clock = pygame.time.Clock()

    player = Player()
    bullets = []
    enemies = []
    particles = []
    stars = [Star() for _ in range(50)] # 背景星星
    
    score = 0
    enemy_spawn_timer = 0
    difficulty_multiplier = 1.0
    state = "START" # START, PLAYING, GAMEOVER

    running = True
    while running:
        # 1. 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if event.type == pygame.KEYDOWN:
                if state == "START":
                    if event.key == pygame.K_SPACE:
                        state = "PLAYING"
                        # 重置游戏
                        player = Player()
                        bullets = []
                        enemies = []
                        particles = []
                        score = 0
                        difficulty_multiplier = 1.0
                elif state == "GAMEOVER":
                    if event.key == pygame.K_SPACE:
                        state = "START"

        # 2. 逻辑更新
        # 更新背景星星 (始终运行)
        for star in stars:
            star.update()

        if state == "PLAYING":
            keys = pygame.key.get_pressed()
            player.move(keys)
            
            # 射击
            if keys[pygame.K_SPACE]:
                bullet = player.shoot()
                if bullet:
                    bullets.append(bullet)

            # 更新子弹
            for b in bullets[:]:
                b.update()
                if not b.active:
                    bullets.remove(b)

            # 生成敌人
            enemy_spawn_timer -= 1
            if enemy_spawn_timer <= 0:
                enemies.append(Enemy(difficulty_multiplier))
                # 随分数增加难度
                spawn_rate = max(20, 60 - int(score / 5))
                enemy_spawn_timer = spawn_rate
            
            # 更新敌人
            for e in enemies[:]:
                e.update()
                if not e.active:
                    enemies.remove(e)
                    continue
                
                # 碰撞检测：敌人撞玩家
                if player.alive and player.rect.colliderect(e.rect):
                    player.alive = False
                    # 玩家死亡爆炸
                    for _ in range(50):
                        particles.append(Particle(player.rect.centerx, player.rect.centery))
                    state = "GAMEOVER"
                
                # 碰撞检测：子弹打敌人
                for b in bullets[:]:
                    if b.active and b.rect.colliderect(e.rect):
                        e.active = False
                        b.active = False
                        if e in enemies: enemies.remove(e)
                        if b in bullets: bullets.remove(b)
                        
                        score += 1
                        # 每10分增加难度
                        if score % 10 == 0:
                            difficulty_multiplier += 0.1
                        
                        # 敌人爆炸粒子
                        for _ in range(15):
                            particles.append(Particle(e.rect.centerx, e.rect.centery))
                        break

            # 更新粒子
            for p in particles[:]:
                if not p.update():
                    particles.remove(p)

        # 3. 绘制渲染
        screen.fill(COLOR_BG)
        
        # 画星星
        for star in stars:
            star.draw(screen)

        if state != "START":
            for b in bullets:
                b.draw(screen)
            for e in enemies:
                e.draw(screen)
            for p in particles:
                p.draw(screen)
            
            if player.alive or state == "GAMEOVER": # 死亡后最后一帧也要画或者不画，这里选择不画玩家只画粒子
                 if player.alive:
                    player.draw(screen)

        # UI 显示
        draw_text(screen, f"Score: {score}", 30, 80, 40, center=False)

        if state == "START":
            draw_text(screen, "太空射击战", 60, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 50)
            draw_text(screen, "按 [空格] 开始游戏", 30, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20)
            draw_text(screen, "WASD/方向键移动 | 空格射击", 20, SCREEN_WIDTH//2, SCREEN_HEIGHT - 40, (150, 150, 150))
        
        elif state == "GAMEOVER":
            # 半透明遮罩
            s = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
            s.set_alpha(180)
            s.fill((0, 0, 0))
            screen.blit(s, (0, 0))
            
            draw_text(screen, "GAME OVER", 70, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 40, (255, 50, 50))
            draw_text(screen, f"最终得分: {score}", 40, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20)
            draw_text(screen, "按 [空格] 返回主菜单", 25, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 70)

        pygame.display.flip()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()