import pygame
import sys
import random

# 初始化
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("加强版滑雪模拟器")
clock = pygame.time.Clock()
FPS = 60

# 颜色定义
WHITE = (255, 255, 255)
SKY_BLUE = (135, 206, 235)
DEEP_SKY = (100, 180, 220)
TREE_GREEN = (22, 100, 22)
TREE_TRUNK = (80, 40, 20)
ROCK_GRAY = (80, 80, 80)
PLAYER_RED = (200, 0, 0)
PLAYER_BLUE = (0, 100, 200)
SNOW_FLAKE = (240, 240, 255)
SPEED_LINE = (200, 200, 200)
HEART_RED = (255, 30, 30)
YELLOW = (255, 220, 0)
BLACK = (0, 0, 0)

# 全局设置
base_speed = 5
max_speed = 14
min_speed = 3
scroll_y = 0
score = 0
combo = 0  # 连击加分
lives = 3  # 生命值
game_over = False
game_pause = False
difficulty = 1  # 难度等级 1~5

# 物理参数
jump_vel = 0
gravity = 0.8
on_ground = True
is_fall = False  # 是否摔倒
fall_timer = 0

# 道具类型
ITEM_SPEED = 1
ITEM_SHIELD = 2
ITEM_HEART = 3
has_shield = False
shield_timer = 0

# ---------------------- 滑雪者类 ----------------------
class Skier:
    def __init__(self):
        self.x = WIDTH // 2
        self.y = HEIGHT - 120
        self.w = 32
        self.h = 50
        self.vx = 0
        self.tilt = 0  # 身体倾斜角度

    def update(self, keys):
        global jump_vel, on_ground, base_speed, is_fall, fall_timer, has_shield, shield_timer
        if game_over or game_pause:
            return

        # 护盾计时
        if has_shield:
            shield_timer -= 1
            if shield_timer <= 0:
                has_shield = False

        # 摔倒状态
        if is_fall:
            fall_timer -= 1
            self.tilt = 45
            if fall_timer <= 0:
                is_fall = False
                self.tilt = 0
            return

        # 左右移动 + 身体倾斜
        self.vx = 0
        if keys[pygame.K_LEFT] and self.x > 25:
            self.vx = -7
            self.tilt = -15
        elif keys[pygame.K_RIGHT] and self.x < WIDTH - 25:
            self.vx = 7
            self.tilt = 15
        else:
            self.tilt = 0
        self.x += self.vx

        # 加/减速
        if keys[pygame.K_DOWN] and base_speed < max_speed:
            base_speed += 0.15
        if keys[pygame.K_UP] and base_speed > min_speed:
            base_speed -= 0.15

        # 跳跃
        if keys[pygame.K_SPACE] and on_ground:
            jump_vel = -16
            on_ground = False

        # 跳跃重力
        jump_vel += gravity
        self.y += jump_vel
        if self.y > HEIGHT - 120:
            self.y = HEIGHT - 120
            jump_vel = 0
            on_ground = True

    def draw(self):
        # 倾斜绘制，模拟转弯姿态
        cx, cy = self.x, self.y
        # 头部
        pygame.draw.circle(screen, PLAYER_BLUE, (cx, cy - 10), 12)
        # 身体
        body_x1 = cx - 16 + self.tilt
        body_x2 = cx + 16 + self.tilt
        pygame.draw.rect(screen, PLAYER_RED, (body_x1, cy, 32, 40))
        # 滑雪板
        board_y = cy + 40
        pygame.draw.rect(screen, BLACK, (cx - 22 + self.tilt//2, board_y, 44, 6))

        # 护盾特效
        if has_shield:
            pygame.draw.circle(screen, (100, 200, 255), (cx, cy + 20), 35, 3)

    def get_rect(self):
        return pygame.Rect(self.x - 16, self.y, 32, 46)

# ---------------------- 障碍物类 ----------------------
class Obstacle:
    def __init__(self, y):
        self.x = random.randint(40, WIDTH - 40)
        self.y = y
        self.type = random.choice(["tree", "rock"])
        if self.type == "tree":
            self.w = 32
            self.h = 65
        else:
            self.w = 45
            self.h = 28

    def update(self):
        self.y += base_speed * (1 + difficulty * 0.1)

    def draw(self):
        if self.type == "tree":
            # 树干
            pygame.draw.rect(screen, TREE_TRUNK, (self.x+10, self.y+30, 12, 35))
            # 树冠
            pygame.draw.circle(screen, TREE_GREEN, (self.x+16, self.y+20), 22)
        else:
            pygame.draw.ellipse(screen, ROCK_GRAY, (self.x, self.y, self.w, self.h))

    def get_rect(self):
        return pygame.Rect(self.x, self.y, self.w, self.h)

# ---------------------- 雪花加分类 ----------------------
class SnowFlake:
    def __init__(self, y):
        self.x = random.randint(30, WIDTH - 30)
        self.y = y
        self.r = 9

    def update(self):
        self.y += base_speed * (1 + difficulty * 0.1)

    def draw(self):
        pygame.draw.circle(screen, SNOW_FLAKE, (self.x, self.y), self.r)

    def get_rect(self):
        return pygame.Rect(self.x - self.r, self.y - self.r, self.r*2, self.r*2)

# ---------------------- 道具类 ----------------------
class Item:
    def __init__(self, y):
        self.x = random.randint(50, WIDTH - 50)
        self.y = y
        self.r = 12
        self.type = random.choice([ITEM_SPEED, ITEM_SHIELD, ITEM_HEART])

    def update(self):
        self.y += base_speed * (1 + difficulty * 0.1)

    def draw(self):
        if self.type == ITEM_SPEED:
            pygame.draw.circle(screen, YELLOW, (self.x, self.y), self.r)
        elif self.type == ITEM_SHIELD:
            pygame.draw.circle(screen, (0, 150, 255), (self.x, self.y), self.r)
        elif self.type == ITEM_HEART:
            pygame.draw.circle(screen, HEART_RED, (self.x, self.y), self.r)

    def get_rect(self):
        return pygame.Rect(self.x - self.r, self.y - self.r, self.r*2, self.r*2)

# ---------------------- 雪地轨迹/特效 ----------------------
class SnowTrace:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.alpha = 180

    def update(self):
        self.y += base_speed
        self.alpha -= 3

    def draw(self):
        s = pygame.Surface((8,8), pygame.SRCALPHA)
        s.fill((255,255,255,self.alpha))
        screen.blit(s, (self.x, self.y))

# ---------------------- 重置游戏 ----------------------
def reset_game():
    global skier, obstacles, snowflakes, items, traces
    global scroll_y, score, lives, game_over, game_pause, difficulty
    global base_speed, combo, is_fall, has_shield, shield_timer, fall_timer

    skier = Skier()
    obstacles = []
    snowflakes = []
    items = []
    traces = []

    scroll_y = 0
    score = 0
    combo = 0
    lives = 3
    base_speed = 5
    difficulty = 1
    game_over = False
    game_pause = False
    is_fall = False
    fall_timer = 40
    has_shield = False
    shield_timer = 0

reset_game()

# 字体
font_small = pygame.font.Font(None, 26)
font_mid = pygame.font.Font(None, 36)
font_big = pygame.font.Font(None, 55)

# ---------------------- 主循环 ----------------------
while True:
    # 渐变天空背景
    screen.fill(DEEP_SKY)

    keys = pygame.key.get_pressed()
    event_list = pygame.event.get()
    for e in event_list:
        if e.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if e.type == pygame.KEYDOWN:
            # 暂停
            if e.key == pygame.K_ESCAPE and not game_over:
                game_pause = not game_pause
            # 重启
            if e.key == pygame.K_r and game_over:
                reset_game()

    if not game_over and not game_pause:
        skier.update(keys)

        # 动态提升难度（分数越高难度越大）
        difficulty = min(5, 1 + score // 800)

        # 生成雪地轨迹
        if random.random() < 0.2:
            traces.append(SnowTrace(skier.x, skier.y + 40))

        # 随机生成元素（难度越高生成越多）
        obs_rate = 0.02 + difficulty * 0.008
        flake_rate = 0.03 + difficulty * 0.005
        item_rate = 0.008

        if random.random() < obs_rate:
            obstacles.append(Obstacle(-60))
        if random.random() < flake_rate:
            snowflakes.append(SnowFlake(-40))
        if random.random() < item_rate:
            items.append(Item(-35))

        # 更新轨迹
        for t in traces[:]:
            t.update()
            if t.alpha <= 0 or t.y > HEIGHT:
                traces.remove(t)

        # 更新障碍物 + 碰撞检测
        player_rect = skier.get_rect()
        for o in obstacles[:]:
            o.update()
            if o.y > HEIGHT:
                obstacles.remove(o)
                continue
            if player_rect.colliderect(o.get_rect()):
                if has_shield:
                    has_shield = False
                    obstacles.remove(o)
                    continue
                # 受伤摔倒
                if not is_fall:
                    lives -= 1
                    is_fall = True
                    fall_timer = 40
                    combo = 0
                    if lives <= 0:
                        game_over = True

        # 雪花收集 连击加分
        for s in snowflakes[:]:
            s.update()
            if s.y > HEIGHT:
                snowflakes.remove(s)
                combo = 0
                continue
            if player_rect.colliderect(s.get_rect()):
                combo += 1
                add = 5 + combo * 2
                score += add
                snowflakes.remove(s)

        # 道具拾取
        for it in items[:]:
            it.update()
            if it.y > HEIGHT:
                items.remove(it)
                continue
            if player_rect.colliderect(it.get_rect()):
                if it.type == ITEM_SPEED:
                    base_speed = min(max_speed, base_speed + 2)
                elif it.type == ITEM_SHIELD:
                    has_shield = True
                    shield_timer = 300
                elif it.type == ITEM_HEART:
                    lives = min(5, lives + 1)
                items.remove(it)

        # 基础分数增长
        score += 1

    # 绘制倾斜雪道（模拟下坡）
    slope_offset = int(base_speed * 2)
    pygame.draw.polygon(screen, WHITE, [
        (-slope_offset, 120),
        (WIDTH + slope_offset, 120),
        (WIDTH, HEIGHT),
        (0, HEIGHT)
    ])

    # 绘制雪地轨迹
    for t in traces:
        t.draw()

    # 绘制所有元素
    for o in obstacles:
        o.draw()
    for s in snowflakes:
        s.draw()
    for it in items:
        it.draw()
    skier.draw()

    # ========== UI界面 ==========
    # 分数、速度、难度
    score_txt = font_mid.render(f"Score: {score}", True, BLACK)
    speed_txt = font_small.render(f"Speed: {round(base_speed,1)}", True, BLACK)
    diff_txt = font_small.render(f"Level: {difficulty}", True, BLACK)
    combo_txt = font_small.render(f"Combo: {combo}", True, YELLOW)
    screen.blit(score_txt, (10, 10))
    screen.blit(speed_txt, (10, 45))
    screen.blit(diff_txt, (10, 70))
    screen.blit(combo_txt, (10, 95))

    # 生命值心形
    for i in range(lives):
        pygame.draw.circle(screen, HEART_RED, (WIDTH - 30 - i*25, 20), 10)

    # 护盾状态
    if has_shield:
        shield_txt = font_small.render("Shield ON", True, (0,150,255))
        screen.blit(shield_txt, (WIDTH - 100, 50))

    # 暂停界面
    if game_pause and not game_over:
        overlay = pygame.Surface((WIDTH, HEIGHT))
        overlay.set_alpha(120)
        overlay.fill(BLACK)
        screen.blit(overlay, (0,0))
        pause_txt = font_big.render("PAUSED", True, WHITE)
        tip_txt = font_mid.render("Press ESC to Resume", True, WHITE)
        screen.blit(pause_txt, (WIDTH//2 - pause_txt.get_width()//2, 220))
        screen.blit(tip_txt, (WIDTH//2 - tip_txt.get_width()//2, 300))

    # 游戏结束界面
    if game_over:
        overlay = pygame.Surface((WIDTH, HEIGHT))
        overlay.set_alpha(150)
        overlay.fill(BLACK)
        screen.blit(overlay, (0,0))
        over_txt = font_big.render("GAME OVER", True, HEART_RED)
        final_score = font_mid.render(f"Final Score: {score}", True, WHITE)
        restart_txt = font_mid.render("Press R to Restart", True, WHITE)
        screen.blit(over_txt, (WIDTH//2 - over_txt.get_width()//2, 200))
        screen.blit(final_score, (WIDTH//2 - final_score.get_width()//2, 280))
        screen.blit(restart_txt, (WIDTH//2 - restart_txt.get_width()//2, 340))

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