import pygame
import random
import math
from pygame.locals import *

# 初始化pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
GRAVITY = 0.5
FRICTION = 0.98
SKIER_SPEED = 8
MAX_TILT = 45
TREE_SPAWN_RATE = 0.02
ROCK_SPAWN_RATE = 0.01
FLAGS_PER_LEVEL = 10

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (135, 206, 250)
RED = (220, 20, 60)
GREEN = (34, 139, 34)
BROWN = (139, 69, 19)
YELLOW = (255, 215, 0)
PURPLE = (147, 112, 219)

class Skier:
    def __init__(self):
        self.reset()
        
    def reset(self):
        self.x = SCREEN_WIDTH // 2
        self.y = 100
        self.speed_x = 0
        self.speed_y = 0
        self.tilt = 0  # 倾斜角度
        self.score = 0
        self.lives = 3
        self.on_ground = True
        self.jumping = False
        self.jump_power = 0
        self.flags_passed = 0
        self.level = 1
        
    def update(self, keys):
        # 控制滑雪者
        if keys[K_LEFT] or keys[K_a]:
            self.speed_x -= 0.5
            self.tilt = max(-MAX_TILT, self.tilt - 3)
        elif keys[K_RIGHT] or keys[K_d]:
            self.speed_x += 0.5
            self.tilt = min(MAX_TILT, self.tilt + 3)
        else:
            # 逐渐恢复平衡
            if self.tilt > 0:
                self.tilt -= 1
            elif self.tilt < 0:
                self.tilt += 1
                
        # 跳跃
        if (keys[K_SPACE] or keys[K_UP] or keys[K_w]) and self.on_ground:
            self.jumping = True
            self.jump_power = 12
            self.on_ground = False
            
        # 应用重力
        if not self.on_ground:
            self.speed_y += GRAVITY
            self.jump_power -= GRAVITY
            
        # 限制最大速度
        self.speed_x = max(-SKIER_SPEED, min(SKIER_SPEED, self.speed_x))
        self.speed_y = max(-SKIER_SPEED * 2, min(SKIER_SPEED * 2, self.speed_y))
        
        # 应用摩擦力
        if self.on_ground:
            self.speed_x *= FRICTION
            
        # 更新位置
        self.x += self.speed_x
        self.y += self.speed_y
        
        # 边界检查
        if self.x < 30:
            self.x = 30
            self.speed_x = abs(self.speed_x) * 0.5
        if self.x > SCREEN_WIDTH - 30:
            self.x = SCREEN_WIDTH - 30
            self.speed_x = -abs(self.speed_x) * 0.5
            
        # 地面检测
        ground_level = SCREEN_HEIGHT - 50
        if self.y > ground_level:
            self.y = ground_level
            self.speed_y = 0
            self.on_ground = True
            self.jumping = False
            
        # 空中状态
        if self.y < ground_level:
            self.on_ground = False
            
    def draw(self, screen):
        # 绘制滑雪者身体
        body_color = RED if self.on_ground else PURPLE
        body_rect = pygame.Rect(self.x - 8, self.y - 15, 16, 30)
        pygame.draw.ellipse(screen, body_color, body_rect)
        
        # 绘制头部
        head_pos = (int(self.x), int(self.y - 25))
        pygame.draw.circle(screen, (255, 220, 180), head_pos, 10)
        
        # 绘制滑雪板
        ski_left = (self.x - 20 + self.tilt/2, self.y + 10)
        ski_right = (self.x + 20 + self.tilt/2, self.y + 10)
        pygame.draw.line(screen, BLACK, ski_left, ski_right, 4)
        
        # 绘制倾斜指示器
        if abs(self.tilt) > 10:
            tilt_color = RED if self.tilt > 0 else BLUE
            tilt_text = font_small.render(f"Tilt: {int(self.tilt)}°", True, tilt_color)
            screen.blit(tilt_text, (self.x - 30, self.y - 50))
            
    def check_collision(self, obstacles):
        skier_rect = pygame.Rect(self.x - 10, self.y - 20, 20, 40)
        
        for obstacle in obstacles:
            if skier_rect.colliderect(obstacle.rect):
                return obstacle
        return None
        
    def add_score(self, points):
        self.score += points
        # 每1000分升一级
        new_level = self.score // 1000 + 1
        if new_level > self.level:
            self.level = new_level
            return True
        return False

class Obstacle:
    def __init__(self, x, y, obstacle_type):
        self.x = x
        self.y = y
        self.type = obstacle_type
        self.passed = False
        
        if obstacle_type == "tree":
            self.rect = pygame.Rect(x - 15, y - 40, 30, 80)
            self.color = GREEN
        elif obstacle_type == "rock":
            self.rect = pygame.Rect(x - 12, y - 10, 24, 20)
            self.color = BROWN
        elif obstacle_type == "flag":
            self.rect = pygame.Rect(x - 5, y - 30, 10, 60)
            self.color = RED
            self.flag_pole_color = YELLOW
            
    def update(self, speed_y):
        self.y += speed_y
        self.rect.y = self.y - self.rect.height // 2
        
    def draw(self, screen):
        if self.type == "tree":
            # 树干
            trunk_rect = pygame.Rect(self.x - 5, self.y, 10, 30)
            pygame.draw.rect(screen, BROWN, trunk_rect)
            # 树冠
            pygame.draw.circle(screen, self.color, (int(self.x), int(self.y - 20)), 25)
        elif self.type == "rock":
            pygame.draw.ellipse(screen, self.color, self.rect)
            # 添加岩石纹理
            for i in range(3):
                rock_x = self.x - 8 + i * 6
                rock_y = self.y - 5 + i * 3
                pygame.draw.circle(screen, (160, 82, 45), (int(rock_x), int(rock_y)), 3)
        elif self.type == "flag":
            # 旗杆
            pygame.draw.line(screen, self.flag_pole_color, 
                           (self.x, self.y - 30), (self.x, self.y + 30), 4)
            # 旗帜
            flag_points = [
                (self.x, self.y - 20),
                (self.x + 20, self.y - 10),
                (self.x, self.y)
            ]
            pygame.draw.polygon(screen, self.color, flag_points)

class SnowParticle:
    def __init__(self):
        self.reset()
        
    def reset(self):
        self.x = random.randint(0, SCREEN_WIDTH)
        self.y = random.randint(-50, 0)
        self.speed = random.uniform(1, 3)
        self.size = random.randint(2, 5)
        
    def update(self):
        self.y += self.speed
        self.x += random.uniform(-0.5, 0.5)
        
        if self.y > SCREEN_HEIGHT:
            self.reset()
            self.y = -10
            
    def draw(self, screen):
        pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.size)

class SkiSimulator:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("Python 滑雪模拟器")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None, 36)
        self.font_small = pygame.font.Font(None, 24)
        self.font_big = pygame.font.Font(None, 72)
        
        # 游戏对象
        self.skier = Skier()
        self.obstacles = []
        self.snow_particles = [SnowParticle() for _ in range(100)]
        
        # 游戏状态
        self.game_over = False
        self.paused = False
        self.distance = 0
        self.speed_multiplier = 1.0
        
    def spawn_obstacles(self):
        # 随机生成障碍物
        if random.random() < TREE_SPAWN_RATE * self.speed_multiplier:
            x = random.randint(50, SCREEN_WIDTH - 50)
            self.obstacles.append(Obstacle(x, -50, "tree"))
            
        if random.random() < ROCK_SPAWN_RATE * self.speed_multiplier:
            x = random.randint(50, SCREEN_WIDTH - 50)
            self.obstacles.append(Obstacle(x, -50, "rock"))
            
        # 生成旗帜（每级固定数量）
        if len([o for o in self.obstacles if o.type == "flag"]) < FLAGS_PER_LEVEL:
            if random.random() < 0.01 * self.speed_multiplier:
                x = random.randint(50, SCREEN_WIDTH - 50)
                self.obstacles.append(Obstacle(x, -50, "flag"))
                
    def update_obstacles(self):
        # 更新障碍物位置
        base_speed = 5 + self.skier.level * 0.5
        for obstacle in self.obstacles[:]:
            obstacle.update(base_speed * self.speed_multiplier)
            
            # 移除屏幕外的障碍物
            if obstacle.y > SCREEN_HEIGHT + 100:
                self.obstacles.remove(obstacle)
                
            # 检查是否通过了旗帜
            if (obstacle.type == "flag" and not obstacle.passed and 
                obstacle.y > self.skier.y):
                obstacle.passed = True
                self.skier.flags_passed += 1
                level_up = self.skier.add_score(100)
                if level_up:
                    self.show_level_up()
                    
    def show_level_up(self):
        # 显示升级消息
        level_text = self.font_big.render(f"LEVEL {self.skier.level}", True, YELLOW)
        text_rect = level_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2))
        
        # 短暂显示
        self.screen.blit(level_text, text_rect)
        pygame.display.flip()
        pygame.time.delay(1500)
        
    def check_collisions(self):
        collision = self.skier.check_collision(self.obstacles)
        if collision:
            if collision.type == "tree":
                self.skier.lives -= 1
                self.skier.speed_x *= -0.5  # 反弹
                self.skier.speed_y = -5
                self.obstacles.remove(collision)
                
                if self.skier.lives <= 0:
                    self.game_over = True
                    
            elif collision.type == "rock":
                self.skier.lives -= 1
                self.skier.speed_x *= -0.3
                self.obstacles.remove(collision)
                
                if self.skier.lives <= 0:
                    self.game_over = True
                    
    def update_snow(self):
        for particle in self.snow_particles:
            particle.update()
            
    def draw_background(self):
        # 渐变天空
        for y in range(SCREEN_HEIGHT):
            color_value = 135 + (y / SCREEN_HEIGHT) * 120
            color = (min(255, color_value), min(255, color_value + 50), 255)
            pygame.draw.line(self.screen, color, (0, y), (SCREEN_WIDTH, y))
            
        # 远山
        for i in range(3):
            mountain_height = 80 + i * 30
            mountain_width = 200 + i * 100
            mountain_x = (i * 300 - self.distance * 0.2) % (SCREEN_WIDTH + 400) - 200
            points = [
                (mountain_x, SCREEN_HEIGHT - 50),
                (mountain_x + mountain_width//2, SCREEN_HEIGHT - 50 - mountain_height),
                (mountain_x + mountain_width, SCREEN_HEIGHT - 50)
            ]
            pygame.draw.polygon(self.screen, (100, 100, 100), points)
            
        # 地面
        ground_rect = pygame.Rect(0, SCREEN_HEIGHT - 50, SCREEN_WIDTH, 50)
        pygame.draw.rect(self.screen, WHITE, ground_rect)
        
        # 雪地纹理
        for i in range(20):
            snow_x = (i * 50 - self.distance) % SCREEN_WIDTH
            pygame.draw.circle(self.screen, (240, 240, 240), (int(snow_x), SCREEN_HEIGHT - 25), 10)
            
    def draw_ui(self):
        # 分数
        score_text = self.font.render(f"Score: {self.skier.score}", True, BLACK)
        self.screen.blit(score_text, (10, 10))
        
        # 生命值
        lives_text = self.font.render(f"Lives: {self.skier.lives}", True, BLACK)
        self.screen.blit(lives_text, (10, 50))
        
        # 等级
        level_text = self.font.render(f"Level: {self.skier.level}", True, BLACK)
        self.screen.blit(level_text, (10, 90))
        
        # 旗帜计数
        flags_text = self.font.render(f"Flags: {self.skier.flags_passed}/{FLAGS_PER_LEVEL}", True, BLACK)
        self.screen.blit(flags_text, (10, 130))
        
        # 速度指示器
        speed = math.sqrt(self.skier.speed_x**2 + self.skier.speed_y**2)
        speed_text = self.font_small.render(f"Speed: {speed:.1f}", True, BLACK)
        self.screen.blit(speed_text, (SCREEN_WIDTH - 120, 10))
        
        # 暂停提示
        if self.paused:
            pause_text = self.font_big.render("PAUSED", True, RED)
            text_rect = pause_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2))
            self.screen.blit(pause_text, text_rect)
            
        # 游戏结束
        if self.game_over:
            game_over_text = self.font_big.render("GAME OVER", True, RED)
            text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 50))
            self.screen.blit(game_over_text, text_rect)
            
            final_score_text = self.font.render(f"Final Score: {self.skier.score}", True, BLACK)
            score_rect = final_score_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20))
            self.screen.blit(final_score_text, score_rect)
            
            restart_text = self.font.render("Press R to Restart", True, BLACK)
            restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 70))
            self.screen.blit(restart_text, restart_rect)
            
    def run(self):
        global font_small
        font_small = self.font_small
        
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == QUIT:
                    running = False
                elif event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        running = False
                    elif event.key == K_p:
                        self.paused = not self.paused
                    elif event.key == K_r and self.game_over:
                        self.restart()
                        
            if not self.paused and not self.game_over:
                # 获取按键状态
                keys = pygame.key.get_pressed()
                
                # 更新游戏对象
                self.skier.update(keys)
                self.update_obstacles()
                self.update_snow()
                self.spawn_obstacles()
                self.check_collisions()
                
                # 更新距离和速度倍数
                self.distance += 1
                self.speed_multiplier = 1.0 + self.distance / 5000
                
            # 绘制
            self.draw_background()
            
            # 绘制雪花
            for particle in self.snow_particles:
                particle.draw(self.screen)
                
            # 绘制障碍物
            for obstacle in self.obstacles:
                obstacle.draw(self.screen)
                
            # 绘制滑雪者
            self.skier.draw(self.screen)
            
            # 绘制UI
            self.draw_ui()
            
            pygame.display.flip()
            self.clock.tick(FPS)
            
        pygame.quit()
        
    def restart(self):
        self.skier.reset()
        self.obstacles.clear()
        self.distance = 0
        self.speed_multiplier = 1.0
        self.game_over = False
        self.paused = False

# 启动游戏
if __name__ == "__main__":
    game = SkiSimulator()
    game.run()