import pygame
import random
import sys
import math

# --- 初始化 Pygame ---
pygame.init()

# --- 常量定义 ---
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60

# 颜色定义
BLACK = (10, 10, 20)      # 深空背景
WHITE = (255, 255, 255)
BLUE = (0, 150, 255)      # 玩家
RED = (255, 50, 50)       # 敌人
YELLOW = (255, 255, 0)    # 星星/粒子
ORANGE = (255, 165, 0)

# 游戏设置
PLAYER_SPEED = 8
INITIAL_ENEMY_SPEED = 4
INITIAL_SPAWN_RATE = 40   # 帧数间隔，越小越频繁
SPEED_INCREMENT = 0.05    # 每帧增加的速度
SPAWN_DECREMENT = 0.05    # 每帧减少的生成间隔

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pygame 飞行躲避 (修复版)")
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 24)
large_font = pygame.font.SysFont("Arial", 48)


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        # 创建一个简单的三角形飞机形状
        self.image = pygame.Surface((40, 40), pygame.SRCALPHA)
        pygame.draw.polygon(self.image, BLUE, [(20, 0), (0, 40), (40, 40)])
        self.rect = self.image.get_rect()
        self.rect.centerx = SCREEN_WIDTH // 2
        self.rect.bottom = SCREEN_HEIGHT - 20
        self.speed_x = 0
        self.speed_y = 0

    def update(self):
        # --- 键盘控制 (稳定版) ---
        keys = pygame.key.get_pressed()
        self.speed_x = 0
        self.speed_y = 0

        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.speed_x = -PLAYER_SPEED
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.speed_x = PLAYER_SPEED
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            self.speed_y = -PLAYER_SPEED
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.speed_y = PLAYER_SPEED

        # 应用速度
        self.rect.x += self.speed_x
        self.rect.y += self.speed_y

        # --- 边界检查 (防止飞出屏幕) ---
        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.right > SCREEN_WIDTH:
            self.rect.right = SCREEN_WIDTH
        if self.rect.top < 0:
            self.rect.top = 0
        if self.rect.bottom > SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT

        # --- 鼠标控制 (已禁用，如需开启请取消下方注释) ---
        # 注意：开启鼠标控制后，键盘控制将失效，二者不建议同时开启
        """
        mouse_x, mouse_y = pygame.mouse.get_pos()
        # 只有当鼠标在游戏窗口内时才跟随
        if pygame.mouse.get_focused():
             # 简单的平滑跟随算法
             if abs(self.rect.centerx - mouse_x) > 5:
                 self.rect.centerx += (mouse_x - self.rect.centerx) * 0.1
             if abs(self.rect.centery - mouse_y) > 5:
                 self.rect.centery += (mouse_y - self.rect.centery) * 0.1
        """


class Enemy(pygame.sprite.Sprite):
    def __init__(self, speed):
        super().__init__()
        size = random.randint(20, 50)
        self.image = pygame.Surface((size, size), pygame.SRCALPHA)
        # 画一个圆形陨石
        pygame.draw.circle(self.image, RED, (size//2, size//2), size//2)
        # 加点细节
        pygame.draw.circle(self.image, ORANGE,
                           (size//2 - 5, size//2 - 5), size//6)

        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(0, SCREEN_WIDTH - size)
        self.rect.y = random.randrange(-100, -40)
        self.speed_y = speed

    def update(self):
        self.rect.y += self.speed_y
        if self.rect.top > SCREEN_HEIGHT:
            self.kill()


class Particle(pygame.sprite.Sprite):
    """简单的爆炸粒子效果"""

    def __init__(self, x, y):
        super().__init__()
        size = random.randint(3, 8)
        self.image = pygame.Surface((size, size))
        color = random.choice([YELLOW, ORANGE, RED])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        # 随机爆炸方向
        angle = random.uniform(0, 2 * math.pi)
        speed = random.uniform(2, 6)
        self.vel_x = math.cos(angle) * speed
        self.vel_y = math.sin(angle) * speed
        self.life = 30  # 存在帧数

    def update(self):
        self.rect.x += self.vel_x
        self.rect.y += self.vel_y
        self.life -= 1
        if self.life <= 0:
            self.kill()


def draw_text(surf, text, size, x, y, color=WHITE):
    font_obj = pygame.font.SysFont("Arial", size)
    text_surface = font_obj.render(text, True, color)
    text_rect = text_surface.get_rect()
    text_rect.midtop = (x, y)
    surf.blit(text_surface, text_rect)


def show_go_screen(score):
    screen.fill(BLACK)
    draw_text(screen, "GAME OVER", 64, SCREEN_WIDTH /
              2, SCREEN_HEIGHT / 4, RED)
    draw_text(screen, f"Final Score: {score}",
              22, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)
    draw_text(screen, "Press SPACE to Restart or Q to Quit",
              18, SCREEN_WIDTH / 2, SCREEN_HEIGHT * 3 / 4)
    pygame.display.flip()

    waiting = True
    while waiting:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return False
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_q:
                    return False
                if event.key == pygame.K_SPACE:
                    return True
    return False


def main():
    running = True
    game_over = False

    # 精灵组
    all_sprites = pygame.sprite.Group()
    enemies = pygame.sprite.Group()
    particles = pygame.sprite.Group()

    player = Player()
    all_sprites.add(player)

    score = 0
    frame_count = 0
    current_enemy_speed = INITIAL_ENEMY_SPEED
    current_spawn_rate = INITIAL_SPAWN_RATE

    while running:
        if game_over:
            # 游戏结束处理逻辑
            # 播放爆炸动画的小循环
            explosion_frames = 0
            # 如果还没生成粒子，先生成
            if len(particles) == 0:
                for _ in range(30):
                    p = Particle(player.rect.centerx, player.rect.centery)
                    all_sprites.add(p)
                    particles.add(p)

            while explosion_frames < 30 and running:
                clock.tick(FPS)
                particles.update()
                screen.fill(BLACK)
                enemies.draw(screen)
                particles.draw(screen)
                pygame.display.flip()
                explosion_frames += 1
                for ev in pygame.event.get():
                    if ev.type == pygame.QUIT:
                        running = False

            if not running:
                break

            if not show_go_screen(score):
                running = False
                continue

            # 重置游戏
            game_over = False
            all_sprites.empty()
            enemies.empty()
            particles.empty()
            player = Player()
            all_sprites.add(player)
            score = 0
            frame_count = 0
            current_enemy_speed = INITIAL_ENEMY_SPEED
            current_spawn_rate = INITIAL_SPAWN_RATE
            continue

        # --- 事件处理 ---
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # --- 游戏逻辑 ---
        all_sprites.update()

        # 生成敌人
        frame_count += 1
        # 防止 spawn_rate 小于 1 导致除以零错误
        safe_spawn_rate = max(1, int(current_spawn_rate))

        if frame_count % safe_spawn_rate == 0:
            enemy = Enemy(current_enemy_speed)
            all_sprites.add(enemy)
            enemies.add(enemy)

            # 增加难度
            score += 1
            current_enemy_speed += SPEED_INCREMENT
            if current_spawn_rate > 10:
                current_spawn_rate -= SPAWN_DECREMENT

        # 碰撞检测
        hits = pygame.sprite.spritecollide(player, enemies, False)
        if hits:
            player.kill()  # 隐藏玩家
            game_over = True
            # 粒子生成将在上面的 if game_over 块中处理

        # --- 绘制渲染 ---
        screen.fill(BLACK)

        # 画一些背景星星装饰
        if random.random() < 0.1:
            pygame.draw.circle(screen, (50, 50, 50), (random.randint(
                0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT)), 2)

        all_sprites.draw(screen)

        # UI
        draw_text(screen, f"Score: {score}", 18, SCREEN_WIDTH - 60, 10)
        draw_text(screen, f"Speed: {current_enemy_speed:.1f}", 18, 60, 10)

        pygame.display.flip()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    main()
