import pygame
import sys
import random
import math
from enum import Enum

# 初始化pygame
pygame.init()
pygame.mixer.init()

# 窗口设置
WIDTH, HEIGHT = 1000, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("深海捕鱼 - 捕鱼达人")
clock = pygame.time.Clock()

# 颜色定义
BLUE = (30, 60, 120)
LIGHT_BLUE = (100, 150, 200)
GREEN = (50, 150, 50)
RED = (200, 50, 50)
YELLOW = (220, 220, 50)
PURPLE = (180, 80, 220)
ORANGE = (255, 165, 0)
WHITE = (255, 255, 255)
BLACK = (20, 20, 20)
GRAY = (150, 150, 150)
DARK_BLUE = (10, 30, 60)

# 鱼类类型枚举
class FishType(Enum):
    SMALL = 1    # 小鱼
    MEDIUM = 2   # 中等鱼
    LARGE = 3    # 大鱼
    SHARK = 4    # 鲨鱼
    GOLD = 5     # 金鱼

# 鱼类类
class Fish:
    def __init__(self, fish_type):
        self.type = fish_type
        self.setup_by_type()
        
        # 随机位置
        if random.random() < 0.5:  # 从左或右边出现
            self.x = random.choice([-self.width, WIDTH])
            self.y = random.randint(50, HEIGHT - 50)
            self.direction = 1 if self.x < 0 else -1
        else:  # 从上或下边出现
            self.x = random.randint(50, WIDTH - 50)
            self.y = random.choice([-self.height, HEIGHT])
            self.direction = 1 if self.y < 0 else -1
            
        # 速度
        self.speed = random.uniform(self.min_speed, self.max_speed)
        
        # 摆动动画
        self.swim_phase = random.uniform(0, 2 * math.pi)
        self.swim_speed = random.uniform(0.05, 0.1)
        self.swim_amplitude = random.uniform(2, 5)
        
        # 状态
        self.caught = False
        self.caught_time = 0
        self.escape_timer = 0
        
    def setup_by_type(self):
        """根据鱼类类型设置属性"""
        if self.type == FishType.SMALL:
            self.width, self.height = 30, 15
            self.color = LIGHT_BLUE
            self.value = 10
            self.health = 1
            self.min_speed, self.max_speed = 1.5, 2.5
        elif self.type == FishType.MEDIUM:
            self.width, self.height = 50, 25
            self.color = GREEN
            self.value = 25
            self.health = 2
            self.min_speed, self.max_speed = 1.2, 2.0
        elif self.type == FishType.LARGE:
            self.width, self.height = 80, 40
            self.color = ORANGE
            self.value = 50
            self.health = 3
            self.min_speed, self.max_speed = 0.8, 1.5
        elif self.type == FishType.SHARK:
            self.width, self.height = 120, 60
            self.color = PURPLE
            self.value = 100
            self.health = 5
            self.min_speed, self.max_speed = 1.0, 1.8
        elif self.type == FishType.GOLD:
            self.width, self.height = 40, 20
            self.color = YELLOW
            self.value = 200
            self.health = 1
            self.min_speed, self.max_speed = 2.0, 3.0
    
    def update(self):
        """更新鱼类位置和状态"""
        if not self.caught:
            # 更新游泳摆动
            self.swim_phase += self.swim_speed
            
            # 向中心区域移动
            center_x, center_y = WIDTH // 2, HEIGHT // 2
            dx = center_x - self.x
            dy = center_y - self.y
            distance = math.sqrt(dx*dx + dy*dy)
            
            if distance > 0:
                dx, dy = dx/distance, dy/distance
            
            # 随机游动
            dx += random.uniform(-0.2, 0.2)
            dy += random.uniform(-0.2, 0.2)
            
            # 归一化
            length = math.sqrt(dx*dx + dy*dy)
            if length > 0:
                dx, dy = dx/length, dy/length
            
            # 更新位置
            self.x += dx * self.speed
            self.y += dy * self.speed
            
            # 边界检查
            if self.x < -100:
                self.x = WIDTH + 50
            elif self.x > WIDTH + 100:
                self.x = -50
            if self.y < -100:
                self.y = HEIGHT + 50
            elif self.y > HEIGHT + 100:
                self.y = -50
        
        elif self.escape_timer > 0:
            # 被捕获状态
            self.escape_timer -= 1
            if self.escape_timer <= 0:
                self.caught = False
    
    def draw(self, surface):
        """绘制鱼类"""
        # 计算摆动偏移
        wave_offset = math.sin(self.swim_phase) * self.swim_amplitude
        
        # 根据方向确定绘制位置
        if self.direction < 0:
            x_pos = self.x
        else:
            x_pos = self.x - self.width
        
        # 绘制鱼身
        fish_rect = pygame.Rect(x_pos, self.y + wave_offset, self.width, self.height)
        
        if self.caught:
            # 被捕时闪烁
            if (pygame.time.get_ticks() // 200) % 2 == 0:
                color = self.color
            else:
                color = (min(255, self.color[0] + 50), 
                        min(255, self.color[1] + 50), 
                        min(255, self.color[2] + 50))
        else:
            color = self.color
        
        # 绘制鱼身
        pygame.draw.ellipse(surface, color, fish_rect)
        
        # 绘制鱼尾
        tail_width = self.width // 3
        tail_points = [
            (x_pos, self.y + wave_offset + self.height // 2),
            (x_pos - tail_width, self.y + wave_offset),
            (x_pos - tail_width, self.y + wave_offset + self.height)
        ] if self.direction < 0 else [
            (x_pos + self.width, self.y + wave_offset + self.height // 2),
            (x_pos + self.width + tail_width, self.y + wave_offset),
            (x_pos + self.width + tail_width, self.y + wave_offset + self.height)
        ]
        pygame.draw.polygon(surface, color, tail_points)
        
        # 绘制鱼眼
        eye_radius = self.height // 4
        eye_x = x_pos + self.width - eye_radius*2 if self.direction < 0 else x_pos + eye_radius*2
        pygame.draw.circle(surface, WHITE, (int(eye_x), int(self.y + wave_offset + self.height//2)), eye_radius)
        pygame.draw.circle(surface, BLACK, (int(eye_x), int(self.y + wave_offset + self.height//2)), eye_radius//2)
        
        # 绘制鱼鳍
        fin_height = self.height // 2
        fin_points = [
            (x_pos + self.width//2, self.y + wave_offset - 5),
            (x_pos + self.width//2 - 10, self.y + wave_offset - fin_height),
            (x_pos + self.width//2 + 10, self.y + wave_offset - fin_height)
        ] if self.direction < 0 else [
            (x_pos + self.width//2, self.y + wave_offset - 5),
            (x_pos + self.width//2 - 10, self.y + wave_offset - fin_height),
            (x_pos + self.width//2 + 10, self.y + wave_offset - fin_height)
        ]
        pygame.draw.polygon(surface, color, fin_points)
        
        # 如果被捕获，显示挣扎动画
        if self.caught and self.escape_timer > 0:
            struggle_phase = math.sin(pygame.time.get_ticks() * 0.01) * 5
            fish_rect.x += struggle_phase
            fish_rect.y += struggle_phase
            
            # 绘制挣扎效果
            for i in range(3):
                offset = random.randint(-2, 2)
                pygame.draw.ellipse(surface, color, fish_rect.move(offset, offset), 1)
    
    def try_escape(self, net_strength):
        """尝试逃脱渔网"""
        if not self.caught:
            return False
            
        escape_chance = 0.1 + (self.health * 0.1) - (net_strength * 0.1)
        escape_chance = max(0.05, min(0.9, escape_chance))
        
        if random.random() < escape_chance:
            self.caught = False
            self.escape_timer = 60
            return True
        return False
    
    def take_damage(self, damage):
        """受到伤害"""
        self.health -= damage
        return self.health <= 0

# 渔网类
class Net:
    def __init__(self):
        self.x = WIDTH // 2
        self.y = HEIGHT // 2
        self.radius = 50
        self.strength = 1
        self.level = 1
        self.upgrade_cost = 100
        self.catching = False
        self.catch_radius = 60
        self.catch_power = 1
        self.speed = 5
        self.cooldown = 0
        
    def update(self, keys):
        """更新渔网位置"""
        if self.cooldown > 0:
            self.cooldown -= 1
        
        # 键盘控制
        if keys[pygame.K_w] or keys[pygame.K_UP]:
            self.y -= self.speed
        if keys[pygame.K_s] or keys[pygame.K_DOWN]:
            self.y += self.speed
        if keys[pygame.K_a] or keys[pygame.K_LEFT]:
            self.x -= self.speed
        if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
            self.x += self.speed
            
        # 边界检查
        self.x = max(self.radius, min(self.x, WIDTH - self.radius))
        self.y = max(self.radius, min(self.y, HEIGHT - self.radius))
        
        # 撒网
        if (keys[pygame.K_SPACE] or keys[pygame.K_RETURN]) and self.cooldown == 0:
            self.catching = True
            self.cooldown = 30
        else:
            if self.cooldown == 0:
                self.catching = False
    
    def draw(self, surface):
        """绘制渔网"""
        # 绘制渔网圆圈
        if self.catching:
            # 捕鱼时显示扩展的网
            pygame.draw.circle(surface, YELLOW, (int(self.x), int(self.y)), 
                             self.catch_radius, 2)
            pygame.draw.circle(surface, (255, 255, 100, 100), 
                             (int(self.x), int(self.y)), self.catch_radius, 1)
        
        # 绘制渔网主体
        pygame.draw.circle(surface, WHITE, (int(self.x), int(self.y)), self.radius, 2)
        
        # 绘制网格
        for i in range(8):
            angle = i * math.pi / 4
            x1 = self.x + math.cos(angle) * (self.radius - 10)
            y1 = self.y + math.sin(angle) * (self.radius - 10)
            x2 = self.x + math.cos(angle) * (self.radius + 10)
            y2 = self.y + math.sin(angle) * (self.radius + 10)
            pygame.draw.line(surface, WHITE, (x1, y1), (x2, y2), 1)
        
        # 绘制中心点
        pygame.draw.circle(surface, YELLOW, (int(self.x), int(self.y)), 5)
    
    def upgrade(self):
        """升级渔网"""
        self.level += 1
        self.radius += 5
        self.catch_radius += 10
        self.catch_power += 0.5
        self.strength += 1
        self.upgrade_cost = int(self.upgrade_cost * 1.5)
        return True
    
    def can_upgrade(self, score):
        """检查是否可以升级"""
        return score >= self.upgrade_cost

# 气泡类
class Bubble:
    def __init__(self):
        self.x = random.randint(0, WIDTH)
        self.y = HEIGHT + 10
        self.radius = random.randint(2, 8)
        self.speed = random.uniform(0.5, 1.5)
        self.color = (200, 200, 255, random.randint(100, 200))
    
    def update(self):
        """更新气泡位置"""
        self.y -= self.speed
        self.x += random.uniform(-0.2, 0.2)
        return self.y > -20
    
    def draw(self, surface):
        """绘制气泡"""
        pygame.draw.circle(surface, self.color[:3], (int(self.x), int(self.y)), 
                         self.radius, 1)
        pygame.draw.circle(surface, (255, 255, 255, 150), 
                         (int(self.x - self.radius/3), int(self.y - self.radius/3)), 
                         self.radius//3)

# 粒子效果类
class Particle:
    def __init__(self, x, y, color, particle_type="score"):
        self.x = x
        self.y = y
        self.color = color
        self.type = particle_type
        
        if particle_type == "score":
            self.life = 60
            self.vx = random.uniform(-2, 2)
            self.vy = random.uniform(-3, -1)
            self.size = random.randint(3, 6)
        else:  # capture
            self.life = 30
            self.vx = random.uniform(-1, 1)
            self.vy = random.uniform(-1, 1)
            self.size = random.randint(2, 4)
    
    def update(self):
        """更新粒子"""
        self.x += self.vx
        self.y += self.vy
        self.life -= 1
        self.vy += 0.1  # 重力
        return self.life > 0
    
    def draw(self, surface):
        """绘制粒子"""
        alpha = min(255, self.life * 4)
        if self.type == "score":
            # 分数粒子
            pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), 
                             self.size)
        else:
            # 捕获特效粒子
            pygame.draw.circle(surface, (*self.color, alpha), 
                             (int(self.x), int(self.y)), self.size)

# 游戏主类
class FishingGame:
    def __init__(self):
        self.score = 0
        self.net = Net()
        self.fishes = []
        self.bubbles = []
        self.particles = []
        self.spawn_timer = 0
        self.game_time = 0
        self.font_large = pygame.font.Font(None, 48)
        self.font_medium = pygame.font.Font(None, 32)
        self.font_small = pygame.font.Font(None, 24)
        self.game_over = False
        
        # 生成初始鱼类
        for _ in range(10):
            self.spawn_fish()
    
    def spawn_fish(self):
        """生成新的鱼类"""
        # 根据时间增加难度
        fish_weights = [
            (FishType.SMALL, 40),
            (FishType.MEDIUM, 30),
            (FishType.LARGE, 20),
            (FishType.SHARK, 8),
            (FishType.GOLD, 2)
        ]
        
        # 调整权重
        difficulty = min(self.game_time / 600, 3)  # 随时间增加难度
        fish_weights[3] = (FishType.SHARK, 8 + int(difficulty * 5))
        fish_weights[0] = (FishType.SMALL, 40 - int(difficulty * 5))
        
        # 选择鱼类类型
        total_weight = sum(w for _, w in fish_weights)
        r = random.uniform(0, total_weight)
        cumulative = 0
        fish_type = FishType.SMALL
        
        for ft, weight in fish_weights:
            cumulative += weight
            if r <= cumulative:
                fish_type = ft
                break
        
        self.fishes.append(Fish(fish_type))
    
    def spawn_bubble(self):
        """生成气泡"""
        if random.random() < 0.1:
            self.bubbles.append(Bubble())
    
    def handle_collisions(self):
        """处理碰撞检测"""
        if not self.net.catching:
            return
        
        for fish in self.fishes:
            if fish.caught:
                continue
                
            # 计算渔网和鱼的距离
            dx = self.net.x - fish.x
            dy = self.net.y - fish.y
            distance = math.sqrt(dx*dx + dy*dy)
            
            if distance < self.net.catch_radius + max(fish.width, fish.height)/2:
                # 尝试捕获
                if random.random() < 0.7:  # 捕获概率
                    fish.caught = True
                    fish.escape_timer = 30
                    
                    # 添加捕获特效
                    for _ in range(20):
                        self.particles.append(Particle(fish.x, fish.y, fish.color, "capture"))
    
    def update(self, keys):
        """更新游戏状态"""
        if self.game_over:
            return
        
        self.game_time += 1
        self.spawn_timer += 1
        self.net.update(keys)
        
        # 生成新鱼类
        if self.spawn_timer > 60:  # 每秒最多生成一条鱼
            if len(self.fishes) < 20 + int(self.game_time / 300):  # 随游戏时间增加鱼的数量
                if random.random() < 0.5:
                    self.spawn_fish()
            self.spawn_timer = 0
        
        # 生成气泡
        self.spawn_bubble()
        
        # 更新鱼类
        fishes_to_remove = []
        for fish in self.fishes:
            fish.update()
            
            if fish.caught:
                # 尝试逃脱
                if fish.try_escape(self.net.strength):
                    continue
                
                # 计算到渔网中心的距离
                dx = self.net.x - fish.x
                dy = self.net.y - fish.y
                distance = math.sqrt(dx*dx + dy*dy)
                
                if distance < 20:  # 到达渔网中心
                    # 捕获成功
                    if fish.take_damage(self.net.catch_power):
                        # 添加分数粒子效果
                        for _ in range(10):
                            self.particles.append(Particle(fish.x, fish.y, YELLOW, "score"))
                        
                        self.score += fish.value
                        fishes_to_remove.append(fish)
                        
                        # 显示分数文字
                        score_text = self.font_small.render(f"+{fish.value}", True, YELLOW)
                        self.particles.append(Particle(fish.x, fish.y, YELLOW, "score"))
                
                else:
                    # 被拉向渔网中心
                    pull_strength = 0.1
                    fish.x += dx * pull_strength
                    fish.y += dy * pull_strength
        
        # 移除被捕获的鱼
        for fish in fishes_to_remove:
            if fish in self.fishes:
                self.fishes.remove(fish)
        
        # 更新气泡
        self.bubbles = [b for b in self.bubbles if b.update()]
        
        # 更新粒子
        self.particles = [p for p in self.particles if p.update()]
        
        # 处理碰撞
        self.handle_collisions()
    
    def draw(self, surface):
        """绘制游戏"""
        # 绘制海洋背景
        surface.fill(DARK_BLUE)
        
        # 绘制海底
        pygame.draw.rect(surface, (20, 40, 10), (0, HEIGHT-50, WIDTH, 50))
        
        # 绘制水草
        for i in range(20):
            x = (WIDTH / 20) * i
            height = random.randint(20, 40)
            width = random.randint(3, 8)
            color = (random.randint(20, 60), random.randint(100, 150), random.randint(20, 60))
            pygame.draw.ellipse(surface, color, (x, HEIGHT-50, width, -height))
        
        # 绘制气泡
        for bubble in self.bubbles:
            bubble.draw(surface)
        
        # 绘制鱼类
        for fish in self.fishes:
            fish.draw(surface)
        
        # 绘制粒子效果
        for particle in self.particles:
            particle.draw(surface)
        
        # 绘制渔网
        self.net.draw(surface)
        
        # 绘制UI
        self.draw_ui(surface)
        
        # 游戏结束画面
        if self.game_over:
            self.draw_game_over(surface)
    
    def draw_ui(self, surface):
        """绘制用户界面"""
        # 绘制分数
        score_text = self.font_large.render(f"分数: {self.score}", True, YELLOW)
        surface.blit(score_text, (20, 20))
        
        # 绘制时间
        time_min = self.game_time // 3600
        time_sec = (self.game_time // 60) % 60
        time_text = self.font_medium.render(f"时间: {time_min:02d}:{time_sec:02d}", True, WHITE)
        surface.blit(time_text, (20, 80))
        
        # 绘制渔网等级
        level_text = self.font_medium.render(f"渔网等级: {self.net.level}", True, LIGHT_BLUE)
        surface.blit(level_text, (WIDTH - 200, 20))
        
        # 绘制升级提示
        upgrade_text = self.font_small.render(f"升级需: {self.net.upgrade_cost}分", True, GREEN)
        surface.blit(upgrade_text, (WIDTH - 200, 60))
        
        # 绘制鱼的数量
        fish_count = len(self.fishes)
        count_text = self.font_small.render(f"鱼群: {fish_count}", True, WHITE)
        surface.blit(count_text, (WIDTH - 200, 100))
        
        # 绘制控制说明
        controls = [
            "控制说明:",
            "W/A/S/D 或 ↑/↓/←/→: 移动渔网",
            "空格/回车: 撒网捕鱼",
            "U: 升级渔网",
            "R: 重新开始",
            "ESC: 退出游戏"
        ]
        
        for i, text in enumerate(controls):
            control_text = self.font_small.render(text, True, GRAY)
            surface.blit(control_text, (WIDTH - 300, HEIGHT - 150 + i * 25))
        
        # 绘制鱼的价值说明
        fish_values = [
            "鱼类价值:",
            "小鱼: 10分",
            "中鱼: 25分",
            "大鱼: 50分",
            "鲨鱼: 100分",
            "金鱼: 200分"
        ]
        
        for i, text in enumerate(fish_values):
            value_text = self.font_small.render(text, True, GRAY)
            surface.blit(value_text, (20, HEIGHT - 150 + i * 25))
    
    def draw_game_over(self, surface):
        """绘制游戏结束画面"""
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 150))
        surface.blit(overlay, (0, 0))
        
        game_over_text = self.font_large.render("游戏结束!", True, RED)
        final_score_text = self.font_medium.render(f"最终分数: {self.score}", True, YELLOW)
        time_min = self.game_time // 3600
        time_sec = (self.game_time // 60) % 60
        time_text = self.font_medium.render(f"游戏时间: {time_min:02d}:{time_sec:02d}", True, WHITE)
        restart_text = self.font_medium.render("按 R 键重新开始", True, GREEN)
        quit_text = self.font_medium.render("按 ESC 键退出", True, GRAY)
        
        texts = [game_over_text, final_score_text, time_text, restart_text, quit_text]
        y_start = HEIGHT // 2 - len(texts) * 25
        
        for i, text in enumerate(texts):
            surface.blit(text, (WIDTH//2 - text.get_width()//2, y_start + i * 60))
    
    def handle_event(self, event):
        """处理事件"""
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_u and not self.game_over:
                # 升级渔网
                if self.net.can_upgrade(self.score):
                    self.score -= self.net.upgrade_cost
                    self.net.upgrade()
            
            elif event.key == pygame.K_r:
                # 重新开始游戏
                self.__init__()
            
            elif event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()

# 主函数
def main():
    game = FishingGame()
    
    # 主循环
    running = True
    while running:
        # 处理事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            else:
                game.handle_event(event)
        
        # 获取按键状态
        keys = pygame.key.get_pressed()
        
        # 更新游戏
        game.update(keys)
        
        # 绘制游戏
        game.draw(screen)
        
        # 更新显示
        pygame.display.flip()
        
        # 控制帧率
        clock.tick(60)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()