import pygame
import sys
import random
import math
import time

# 初始化pygame
pygame.init()

# 游戏窗口设置
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("FLY")
clock = pygame.time.Clock()
FPS = 60

# 颜色定义
SKY_COLOR = (135, 206, 235)
CLOUD_COLOR = (255, 255, 255)
PLAYER_COLOR = (255, 100, 100)
PLAYER_ENGINE_COLOR = (255, 200, 100)
ENEMY_COLOR = (100, 100, 255)
BULLET_COLOR = (255, 255, 100)
EXPLOSION_COLOR = (255, 150, 50)
TEXT_COLOR = (255, 255, 255)
TEXT_SHADOW = (0, 0, 0)
NEON_BLUE = (0, 200, 255)
NEON_GREEN = (0, 255, 100)
NEON_RED = (255, 0, 100)
NEON_YELLOW = (255, 255, 0)
NEON_PURPLE = (200, 0, 255)
BUTTON_COLOR = (50, 150, 255)
BUTTON_HOVER = (100, 200, 255)
PROGRESS_COLOR = (100, 200, 255)
PROGRESS_BG_COLOR = (50, 70, 100)

# 创建字体
try:
    font_small = pygame.font.Font(None, 24)
    font_medium = pygame.font.Font(None, 36)
    font_large = pygame.font.Font(None, 48)
    font_huge = pygame.font.Font(None, 72)
    font_score = pygame.font.Font(None, 64)
except:
    font_small = pygame.font.SysFont(None, 24)
    font_medium = pygame.font.SysFont(None, 36)
    font_large = pygame.font.SysFont(None, 48)
    font_huge = pygame.font.SysFont(None, 72)
    font_score = pygame.font.SysFont(None, 64)

# 云朵类
class Cloud:
    def __init__(self, x, y, speed=1):
        self.x = x
        self.y = y
        self.speed = speed
        self.size = random.randint(30, 80)
        self.type = random.choice(["small", "medium", "large"])
        
    def update(self):
        self.x -= self.speed
        
        # 如果云朵移出屏幕，重置到右侧
        if self.x < -100:
            self.x = SCREEN_WIDTH + 50
            self.y = random.randint(20, SCREEN_HEIGHT // 2)
            
    def draw(self, surface):
        # 根据类型确定大小
        if self.type == "small":
            width = self.size
            height = self.size // 2
        elif self.type == "medium":
            width = self.size
            height = self.size // 2.5
        else:  # large
            width = self.size
            height = self.size // 3
            
        # 绘制多层云朵创建立体感
        for i in range(3, 0, -1):
            cloud_width = width + i * 5
            cloud_height = height + i * 3
            alpha = 150 - i * 30
            
            # 主云体
            pygame.draw.ellipse(surface, (*CLOUD_COLOR, alpha), 
                               (self.x - cloud_width//2, self.y, 
                                cloud_width, cloud_height))
            
            # 左侧云朵
            pygame.draw.ellipse(surface, (*CLOUD_COLOR, alpha), 
                               (self.x - cloud_width//2 - cloud_width//3, 
                                self.y + cloud_height//6, 
                                cloud_width//1.5, cloud_height//2))
            
            # 右侧云朵
            pygame.draw.ellipse(surface, (*CLOUD_COLOR, alpha), 
                               (self.x + cloud_width//3, 
                                self.y + cloud_height//6, 
                                cloud_width//1.5, cloud_height//2))

# 玩家飞机类
class Player:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 60
        self.height = 40
        self.speed = 5
        self.health = 100
        self.max_health = 100
        self.score = 0
        self.speed_multiplier = 1.0
        self.bullets = []
        self.last_shot = 0
        self.shoot_delay = 200  # 毫秒
        self.invincible = 0
        self.engine_particles = []
        self.engine_timer = 0
        
    def update(self, keys):
        # 移动控制
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.x -= self.speed * self.speed_multiplier
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.x += self.speed * self.speed_multiplier
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            self.y -= self.speed * self.speed_multiplier
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.y += self.speed * self.speed_multiplier
            
        # 屏幕边界限制
        self.x = max(self.width//2, min(SCREEN_WIDTH - self.width//2, self.x))
        self.y = max(self.height//2, min(SCREEN_HEIGHT - self.height//2, self.y))
        
        # 射击控制
        current_time = pygame.time.get_ticks()
        if keys[pygame.K_SPACE] and current_time - self.last_shot > self.shoot_delay:
            self.shoot()
            self.last_shot = current_time
            
        # 更新子弹
        for bullet in self.bullets[:]:
            bullet.update()
            if bullet.x < 0 or bullet.x > SCREEN_WIDTH or bullet.y < 0:
                self.bullets.remove(bullet)
                
        # 创建引擎粒子
        self.engine_timer += 1
        if self.engine_timer >= 2:
            self.engine_particles.append({
                'x': self.x - self.width//2 - 5,
                'y': self.y + random.randint(-5, 5),
                'size': random.randint(3, 6),
                'speed': random.uniform(1, 3),
                'life': random.randint(20, 40)
            })
            self.engine_timer = 0
            
        # 更新引擎粒子
        for particle in self.engine_particles[:]:
            particle['x'] -= particle['speed']
            particle['life'] -= 1
            if particle['life'] <= 0:
                self.engine_particles.remove(particle)
                
        # 更新无敌时间
        if self.invincible > 0:
            self.invincible -= 1
            
    def shoot(self):
        bullet = Bullet(self.x + self.width//2, self.y)
        self.bullets.append(bullet)
        
    def take_damage(self, damage):
        if self.invincible <= 0:
            self.health -= damage
            self.invincible = 30  # 0.5秒无敌时间
            
    def heal(self, amount):
        self.health = min(self.max_health, self.health + amount)
        
    def get_rect(self):
        return pygame.Rect(self.x - self.width//2, self.y - self.height//2, 
                          self.width, self.height)
        
    def draw(self, surface):
        # 绘制引擎粒子
        for particle in self.engine_particles:
            alpha = int(255 * (particle['life'] / 40))
            pygame.draw.circle(surface, (*PLAYER_ENGINE_COLOR, alpha), 
                             (int(particle['x']), int(particle['y'])), 
                             particle['size'])
            
        # 无敌闪烁效果
        if self.invincible > 0 and self.invincible % 10 < 5:
            return
            
        # 绘制飞机主体
        body_rect = pygame.Rect(self.x - self.width//2, self.y - self.height//2, 
                               self.width, self.height)
        
        # 飞机颜色渐变
        player_color = (
            int(PLAYER_COLOR[0] + (255 - PLAYER_COLOR[0]) * 0.3),
            int(PLAYER_COLOR[1] + (255 - PLAYER_COLOR[1]) * 0.3),
            int(PLAYER_COLOR[2] + (255 - PLAYER_COLOR[2]) * 0.3)
        )
        
        pygame.draw.rect(surface, player_color, body_rect, border_radius=5)
        
        # 绘制飞机细节
        # 驾驶舱
        pygame.draw.circle(surface, NEON_BLUE, (self.x, self.y - 5), 10)
        
        # 机翼
        wing_left = pygame.Rect(self.x - self.width//2 - 10, self.y - 5, 15, 8)
        wing_right = pygame.Rect(self.x + self.width//2 - 5, self.y - 5, 15, 8)
        pygame.draw.rect(surface, player_color, wing_left, border_radius=3)
        pygame.draw.rect(surface, player_color, wing_right, border_radius=3)
        
        # 尾翼
        pygame.draw.polygon(surface, player_color, [
            (self.x + self.width//2, self.y),
            (self.x + self.width//2 + 20, self.y - 10),
            (self.x + self.width//2 + 20, self.y + 10)
        ])
        
        # 引擎火焰
        if random.random() < 0.3:
            flame_height = random.randint(10, 15)
            pygame.draw.ellipse(surface, PLAYER_ENGINE_COLOR, 
                               (self.x - self.width//2 - flame_height, 
                                self.y - 5, 
                                flame_height, 10))
            
        # 绘制子弹
        for bullet in self.bullets:
            bullet.draw(surface)

# 子弹类
class Bullet:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 8
        self.height = 15
        self.speed = 10
        
    def update(self):
        self.x += self.speed
        
    def get_rect(self):
        """修复：添加get_rect方法用于碰撞检测"""
        return pygame.Rect(self.x, self.y, self.width, self.height)
        
    def draw(self, surface):
        # 绘制子弹发光效果
        for i in range(3, 0, -1):
            glow_size = i * 2
            pygame.draw.ellipse(surface, (*BULLET_COLOR, 100 - i*30), 
                               (self.x - glow_size//2, self.y - glow_size//2, 
                                self.width + glow_size, self.height + glow_size))
            
        pygame.draw.ellipse(surface, BULLET_COLOR, 
                           (self.x, self.y, self.width, self.height))

# 敌人类
class Enemy:
    def __init__(self, x, y, enemy_type="normal"):
        self.x = x
        self.y = y
        self.type = enemy_type
        self.speed = random.uniform(2.0, 4.0)
        
        if enemy_type == "normal":
            self.width = 40
            self.height = 40
            self.health = 30
            self.color = ENEMY_COLOR
        elif enemy_type == "fast":
            self.width = 30
            self.height = 30
            self.health = 20
            self.speed = random.uniform(4.0, 6.0)
            self.color = (255, 150, 50)  # 橙色
        elif enemy_type == "tank":
            self.width = 60
            self.height = 60
            self.health = 100
            self.speed = random.uniform(0.5, 1.5)
            self.color = (100, 255, 100)  # 绿色
            
        self.move_pattern = random.choice(["straight", "sin", "wave"])
        self.angle = 0
        self.amplitude = random.randint(20, 50)
        self.frequency = random.uniform(0.05, 0.1)
        
    def update(self):
        if self.move_pattern == "straight":
            self.x -= self.speed
        elif self.move_pattern == "sin":
            self.x -= self.speed
            self.y += math.sin(self.angle) * self.amplitude
            self.angle += self.frequency
        elif self.move_pattern == "wave":
            self.x -= self.speed * 0.8
            self.y += math.sin(self.angle) * self.amplitude
            self.angle += self.frequency * 2
            
    def is_off_screen(self):
        return self.x < -100
        
    def take_damage(self, damage):
        self.health -= damage
        return self.health <= 0
        
    def get_rect(self):
        return pygame.Rect(self.x - self.width//2, self.y - self.height//2, 
                          self.width, self.height)
        
    def draw(self, surface):
        # 绘制敌人
        if self.type == "normal":
            # 普通敌人 - 简单形状
            pygame.draw.rect(surface, self.color, 
                           (self.x - self.width//2, self.y - self.height//2, 
                            self.width, self.height), border_radius=5)
            
            # 装饰
            pygame.draw.circle(surface, (255, 255, 255), 
                             (int(self.x), int(self.y)), 8)
            pygame.draw.circle(surface, (0, 0, 0), 
                             (int(self.x), int(self.y)), 4)
                             
        elif self.type == "fast":
            # 快速敌人 - 三角形
            points = [
                (self.x, self.y - self.height//2),
                (self.x - self.width//2, self.y + self.height//2),
                (self.x + self.width//2, self.y + self.height//2)
            ]
            pygame.draw.polygon(surface, self.color, points)
            
        elif self.type == "tank":
            # 坦克敌人 - 方形
            pygame.draw.rect(surface, self.color, 
                           (self.x - self.width//2, self.y - self.height//2, 
                            self.width, self.height), border_radius=8)
            
            # 炮塔
            pygame.draw.circle(surface, (150, 150, 150), 
                             (int(self.x), int(self.y)), 15)
            
        # 显示血条
        if self.health < 100:
            health_width = 40
            health_height = 5
            max_health = 30 if self.type == "normal" else 20 if self.type == "fast" else 100
            health_ratio = self.health / max_health
            
            # 血条背景
            pygame.draw.rect(surface, (100, 0, 0), 
                           (self.x - health_width//2, self.y - self.height//2 - 10, 
                            health_width, health_height))
            
            # 当前血量
            if health_ratio > 0:
                current_width = int(health_width * health_ratio)
                pygame.draw.rect(surface, (0, 255, 0), 
                               (self.x - health_width//2, self.y - self.height//2 - 10, 
                                current_width, health_height))

# 游戏主类
class FlyingGame:
    def __init__(self):
        self.state = "menu"  # menu, playing, game_over
        self.player = None
        self.enemies = []
        self.clouds = []
        self.score = 0
        self.high_score = 0
        self.wave = 1
        self.enemies_spawned = 0
        self.enemies_to_spawn = 5
        self.spawn_timer = 0
        self.spawn_interval = 120
        self.game_time = 0
        self.init_clouds()
        self.init_menu()
        
    def init_clouds(self):
        """初始化云朵"""
        self.clouds = []
        for _ in range(10):
            x = random.randint(0, SCREEN_WIDTH)
            y = random.randint(20, SCREEN_HEIGHT // 2)
            speed = random.uniform(0.5, 1.5)
            self.clouds.append(Cloud(x, y, speed))
            
    def init_menu(self):
        """初始化菜单"""
        self.buttons = []
        
    def start_game(self):
        """开始游戏"""
        self.state = "playing"
        self.player = Player(100, SCREEN_HEIGHT // 2)
        self.enemies = []
        self.score = 0
        self.wave = 1
        self.enemies_spawned = 0
        self.enemies_to_spawn = 5
        self.spawn_timer = 0
        self.game_time = 0
        
    def spawn_enemy(self):
        """生成敌人"""
        if self.enemies_spawned < self.enemies_to_spawn:
            y = random.randint(50, SCREEN_HEIGHT - 50)
            enemy_type = "normal"
            
            # 根据波数选择敌人类型
            if self.wave >= 3 and random.random() < 0.3:
                enemy_type = "fast"
            if self.wave >= 5 and random.random() < 0.2:
                enemy_type = "tank"
                
            self.enemies.append(Enemy(SCREEN_WIDTH + 50, y, enemy_type))
            self.enemies_spawned += 1
            
    def update(self):
        """更新游戏状态"""
        if self.state == "playing":
            self.game_time += 1/60
            
            # 更新云朵
            for cloud in self.clouds:
                cloud.update()
                
            # 更新玩家
            keys = pygame.key.get_pressed()
            self.player.update(keys)
            
            # 生成敌人
            self.spawn_timer += 1
            if self.spawn_timer >= self.spawn_interval and self.enemies_spawned < self.enemies_to_spawn:
                self.spawn_enemy()
                self.spawn_timer = 0
                
            # 检查波数完成
            if self.enemies_spawned >= self.enemies_to_spawn and len(self.enemies) == 0:
                self.wave += 1
                self.enemies_spawned = 0
                self.enemies_to_spawn = min(15, 5 + self.wave * 2)
                self.spawn_interval = max(60, 120 - self.wave * 5)
                
            # 更新敌人
            for enemy in self.enemies[:]:
                enemy.update()
                
                if enemy.is_off_screen():
                    self.enemies.remove(enemy)
                    
            # 检查子弹和敌人碰撞
            for bullet in self.player.bullets[:]:
                bullet_rect = bullet.get_rect()  # 修复：现在可以使用get_rect()方法
                for enemy in self.enemies[:]:
                    if bullet_rect.colliderect(enemy.get_rect()):
                        if bullet in self.player.bullets:
                            self.player.bullets.remove(bullet)
                        if enemy.take_damage(10):
                            self.score += 100 if enemy.type == "normal" else 150 if enemy.type == "fast" else 300
                            self.enemies.remove(enemy)
                        break
                        
            # 检查敌人和玩家碰撞
            player_rect = self.player.get_rect()
            for enemy in self.enemies:
                if enemy.get_rect().colliderect(player_rect):
                    self.player.take_damage(20)
                    enemy.take_damage(50)
                    
            # 检查游戏结束
            if self.player.health <= 0:
                self.state = "game_over"
                if self.score > self.high_score:
                    self.high_score = self.score
                    
    def draw_background(self, surface):
        """绘制背景"""
        # 天空渐变
        for y in range(SCREEN_HEIGHT):
            ratio = y / SCREEN_HEIGHT
            r = int(SKY_COLOR[0] + (255 - SKY_COLOR[0]) * ratio * 0.3)
            g = int(SKY_COLOR[1] + (255 - SKY_COLOR[1]) * ratio * 0.3)
            b = int(SKY_COLOR[2] + (255 - SKY_COLOR[2]) * ratio * 0.3)
            pygame.draw.line(surface, (r, g, b), (0, y), (SCREEN_WIDTH, y))
            
        # 绘制云朵
        for cloud in self.clouds:
            cloud.draw(screen)
            
    def draw_menu(self, surface):
        """绘制菜单"""
        self.draw_background(surface)
        
        # 标题
        title = font_huge.render("天空飞行大冒险", True, NEON_BLUE)
        title_shadow = font_huge.render("天空飞行大冒险", True, TEXT_SHADOW)
        surface.blit(title_shadow, (SCREEN_WIDTH//2 - title.get_width()//2 + 3, 103))
        surface.blit(title, (SCREEN_WIDTH//2 - title.get_width()//2, 100))
        
        # 开始提示
        start_text = font_medium.render("按任意键开始游戏", True, NEON_GREEN)
        surface.blit(start_text, (SCREEN_WIDTH//2 - start_text.get_width()//2, 200))
        
        # 控制说明
        controls = [
            "控制方式:",
            "W A S D 或方向键: 移动飞机",
            "空格键: 射击",
            "ESC: 返回菜单/退出",
            "",
            "游戏目标:",
            "1. 尽可能飞得更远",
            "2. 射击敌人获取分数",
            "3. 避开敌人的撞击",
            "4. 注意你的血量"
        ]
        
        for i, control in enumerate(controls):
            control_text = font_small.render(control, True, TEXT_COLOR)
            surface.blit(control_text, (50, 300 + i * 25))
            
        # 显示最高分
        if self.high_score > 0:
            high_score_text = font_medium.render(f"最高分: {self.high_score}", True, NEON_YELLOW)
            surface.blit(high_score_text, (SCREEN_WIDTH - 300, 300))
            
    def draw_game(self, surface):
        """绘制游戏"""
        # 绘制背景
        self.draw_background(surface)
        
        # 绘制敌人
        for enemy in self.enemies:
            enemy.draw(surface)
            
        # 绘制玩家
        if self.player:
            self.player.draw(surface)
            
        # 绘制UI
        self.draw_ui(surface)
        
    def draw_ui(self, surface):
        """绘制用户界面"""
        # 分数
        score_text = font_score.render(f"{self.score}", True, NEON_YELLOW)
        surface.blit(score_text, (SCREEN_WIDTH - score_text.get_width() - 20, 20))
        
        # 波数
        wave_text = font_medium.render(f"波数: {self.wave}", True, TEXT_COLOR)
        surface.blit(wave_text, (20, 20))
        
        # 血量条
        health_width = 200
        health_height = 20
        health_ratio = self.player.health / self.player.max_health
        
        # 血量条背景
        pygame.draw.rect(surface, (100, 0, 0), 
                        (20, 60, health_width, health_height), border_radius=5)
        
        # 当前血量
        if health_ratio > 0:
            current_width = int(health_width * health_ratio)
            health_color = NEON_GREEN if health_ratio > 0.5 else NEON_RED
            pygame.draw.rect(surface, health_color, 
                           (20, 60, current_width, health_height), border_radius=5)
            
        # 血量文本
        health_text = font_medium.render(f"血量: {int(self.player.health)}/{self.player.max_health}", True, TEXT_COLOR)
        surface.blit(health_text, (230, 60))
        
        # 剩余敌人
        enemies_left = self.enemies_to_spawn - self.enemies_spawned + len(self.enemies)
        enemy_text = font_small.render(f"剩余敌人: {enemies_left}", True, TEXT_COLOR)
        surface.blit(enemy_text, (20, 100))
        
    def draw_game_over(self, surface):
        """绘制游戏结束界面"""
        # 绘制游戏
        self.draw_game(surface)
        
        # 半透明覆盖层
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
        overlay.set_alpha(150)
        overlay.fill((0, 0, 0))
        surface.blit(overlay, (0, 0))
        
        # 游戏结束标题
        game_over = font_huge.render("游戏结束", True, NEON_RED)
        surface.blit(game_over, (SCREEN_WIDTH//2 - game_over.get_width()//2, 150))
        
        # 显示分数
        score_text = font_large.render(f"最终得分: {self.score}", True, NEON_YELLOW)
        surface.blit(score_text, (SCREEN_WIDTH//2 - score_text.get_width()//2, 250))
        
        # 显示波数
        wave_text = font_medium.render(f"达到波数: {self.wave}", True, TEXT_COLOR)
        surface.blit(wave_text, (SCREEN_WIDTH//2 - wave_text.get_width()//2, 320))
        
        # 显示游戏时间
        time_text = font_medium.render(f"游戏时间: {int(self.game_time)}秒", True, TEXT_COLOR)
        surface.blit(time_text, (SCREEN_WIDTH//2 - time_text.get_width()//2, 370))
        
        # 重新开始提示
        restart_text = font_medium.render("按 R 重新开始，ESC 返回菜单", True, TEXT_COLOR)
        surface.blit(restart_text, (SCREEN_WIDTH//2 - restart_text.get_width()//2, 450))
        
    def handle_events(self):
        """处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
                
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    if self.state == "playing":
                        self.state = "menu"
                    elif self.state == "game_over":
                        self.state = "menu"
                    elif self.state == "menu":
                        pygame.quit()
                        sys.exit()
                        
                elif self.state == "menu":
                    # 按任意键开始游戏
                    self.start_game()
                    
                elif self.state == "game_over" and event.key == pygame.K_r:
                    # 重新开始游戏
                    self.start_game()

    def draw(self, surface):
        """绘制整个游戏"""
        if self.state == "menu":
            self.draw_menu(surface)
        elif self.state == "playing":
            self.draw_game(surface)
        elif self.state == "game_over":
            self.draw_game_over(surface)

def main():
    game = FlyingGame()
    
    while True:
        game.handle_events()
        game.update()
        game.draw(screen)
        pygame.display.flip()
        clock.tick(FPS)

if __name__ == "__main__":
    main()