import pygame
import random
import sys

# --- 初始化 ---
pygame.init()
pygame.font.init()

# --- 常量定义 ---
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 400
FPS = 60

# 颜色定义
COLOR_BG = (20, 20, 30)       # 深蓝黑背景
COLOR_GROUND = (50, 50, 60)   # 地面颜色
COLOR_PLAYER = (0, 255, 150)  # 玩家颜色 (亮绿)
COLOR_OBSTACLE = (255, 50, 50)# 障碍颜色 (红)
COLOR_TEXT = (255, 255, 255)
COLOR_PARTICLE = (255, 200, 50)

# 物理参数
GRAVITY = 0.6
JUMP_STRENGTH = -12
GROUND_Y = SCREEN_HEIGHT - 50
PLAYER_SIZE = 40
OBSTACLE_WIDTH = 30
OBSTACLE_MIN_HEIGHT = 40
OBSTACLE_MAX_HEIGHT = 70

class Particle:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.vx = random.uniform(-2, 2)
        self.vy = random.uniform(-2, 0)
        self.life = 20  # 存活帧数
        self.size = random.randint(3, 6)

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += 0.2  # 粒子重力
        self.life -= 1
        return self.life > 0

    def draw(self, surface):
        pygame.draw.rect(surface, COLOR_PARTICLE, (int(self.x), int(self.y), self.size, self.size))

class Player:
    def __init__(self):
        self.rect = pygame.Rect(100, GROUND_Y - PLAYER_SIZE, PLAYER_SIZE, PLAYER_SIZE)
        self.vel_y = 0
        self.is_jumping = False
        self.jump_count = 0 # 用于二段跳
        self.max_jumps = 2
        self.particles = []

    def jump(self):
        if self.jump_count < self.max_jumps:
            self.vel_y = JUMP_STRENGTH
            self.is_jumping = True
            self.jump_count += 1
            # 生成跳跃粒子
            for _ in range(10):
                self.particles.append(Particle(self.rect.centerx, self.rect.bottom))

    def update(self):
        # 应用重力
        self.vel_y += GRAVITY
        self.rect.y += self.vel_y

        # 地面碰撞检测
        if self.rect.bottom >= GROUND_Y:
            if self.is_jumping:
                # 落地瞬间生成粒子
                for _ in range(15):
                    self.particles.append(Particle(self.rect.centerx, self.rect.bottom))
            
            self.rect.bottom = GROUND_Y
            self.vel_y = 0
            self.is_jumping = False
            self.jump_count = 0

        # 更新粒子
        self.particles = [p for p in self.particles if p.update()]

    def draw(self, surface):
        # 绘制粒子
        for p in self.particles:
            p.draw(surface)
        
        # 绘制玩家 (带一点简单的动画效果：跳跃时变长，奔跑时微动)
        color = COLOR_PLAYER
        if self.is_jumping:
            # 跳跃时稍微拉长
            draw_rect = pygame.Rect(self.rect.x, self.rect.y - 5, self.rect.width, self.rect.height + 5)
        else:
            # 奔跑时轻微晃动模拟步伐
            offset = int(pygame.time.get_ticks() / 100) % 2 * 2
            draw_rect = pygame.Rect(self.rect.x, self.rect.y + offset, self.rect.width, self.rect.height - offset)
        
        pygame.draw.rect(surface, color, draw_rect)
        # 画个眼睛表示方向
        pygame.draw.circle(surface, (0, 0, 0), (draw_rect.right - 10, draw_rect.top + 10), 4)

class Obstacle:
    def __init__(self, speed):
        self.width = OBSTACLE_WIDTH
        self.height = random.randint(OBSTACLE_MIN_HEIGHT, OBSTACLE_MAX_HEIGHT)
        self.rect = pygame.Rect(SCREEN_WIDTH, GROUND_Y - self.height, self.width, self.height)
        self.speed = speed
        self.passed = False

    def update(self):
        self.rect.x -= self.speed

    def draw(self, surface):
        # 绘制障碍，带点立体感
        pygame.draw.rect(surface, COLOR_OBSTACLE, self.rect)
        pygame.draw.rect(surface, (200, 0, 0), self.rect, 2) # 边框

def draw_text(surface, text, size, x, y, color=COLOR_TEXT, center=True):
    font = pygame.font.SysFont('Arial', size, bold=True)
    render = font.render(text, True, color)
    rect = render.get_rect()
    if center:
        rect.center = (x, y)
    else:
        rect.topleft = (x, y)
    surface.blit(render, rect)

def main():
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("Python 极速跑酷")
    clock = pygame.time.Clock()

    player = Player()
    obstacles = []
    
    score = 0
    game_speed = 5
    spawn_timer = 0
    state = "START" # START, PLAYING, GAMEOVER

    running = True
    while running:
        # 1. 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
                    if state == "START":
                        state = "PLAYING"
                        score = 0
                        game_speed = 5
                        obstacles = []
                        player = Player()
                    elif state == "PLAYING":
                        player.jump()
                    elif state == "GAMEOVER":
                        state = "START" # 按任意键回到开始界面

        # 2. 逻辑更新
        if state == "PLAYING":
            player.update()
            
            # 生成障碍
            spawn_timer -= 1
            if spawn_timer <= 0:
                obstacles.append(Obstacle(game_speed))
                # 随机生成间隔，随速度增加间隔变短
                min_gap = int(600 / game_speed) 
                spawn_timer = random.randint(min_gap, min_gap + 40)
            
            # 更新障碍
            for obs in obstacles[:]:
                obs.update()
                if obs.rect.right < 0:
                    obstacles.remove(obs)
                    score += 1
                    # 每得5分加速
                    if score % 5 == 0:
                        game_speed += 0.5
                
                # 碰撞检测
                if player.rect.colliderect(obs.rect):
                    state = "GAMEOVER"

        # 3. 绘制渲染
        screen.fill(COLOR_BG)
        
        # 画地面
        pygame.draw.rect(screen, COLOR_GROUND, (0, GROUND_Y, SCREEN_WIDTH, SCREEN_HEIGHT - GROUND_Y))
        # 画地面线条增加速度感
        line_offset = (pygame.time.get_ticks() * game_speed) % 50
        for i in range(0, SCREEN_WIDTH, 50):
            pygame.draw.line(screen, (70, 70, 80), (i - line_offset, GROUND_Y), (i - line_offset + 20, GROUND_Y), 2)

        # 绘制实体
        if state != "START":
            for obs in obstacles:
                obs.draw(screen)
            player.draw(screen)

        # UI 显示
        if state == "START":
            draw_text(screen, "极速跑酷", 60, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 50)
            draw_text(screen, "按 [空格] 或 [↑] 开始", 30, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20)
            draw_text(screen, "操作：空格/↑ 跳跃 (支持二段跳)", 20, SCREEN_WIDTH//2, SCREEN_HEIGHT - 30, (150, 150, 150))
        
        elif state == "PLAYING":
            draw_text(screen, f"Score: {score}", 30, 80, 40, center=False)
            draw_text(screen, f"Speed: {game_speed:.1f}", 20, 80, 70, (100, 255, 100), center=False)

        elif state == "GAMEOVER":
            # 半透明遮罩
            s = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
            s.set_alpha(150)
            s.fill((0, 0, 0))
            screen.blit(s, (0, 0))
            
            draw_text(screen, "GAME OVER", 60, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 40, (255, 50, 50))
            draw_text(screen, f"最终得分: {score}", 40, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20)
            draw_text(screen, "按 [空格] 重新开始", 25, SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 70)

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

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()