import pygame
import random
import sys
import math

# 初始化pygame
pygame.init()

# 游戏窗口设置
WIDTH, HEIGHT = 800, 400
FPS = 60
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("火柴人跑酷 - 按空格键跳跃，S键下滑")
clock = pygame.time.Clock()

# 颜色定义
SKY_BLUE = (135, 206, 235)  # 天空蓝
GROUND_COLOR = (139, 115, 85)  # 土地色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (34, 139, 34)  # 树绿色
YELLOW = (255, 215, 0)  # 金币黄色
RED = (255, 0, 0)  # 障碍物红色
CLOUD_WHITE = (245, 245, 245)  # 云朵白色
STICKMAN_COLOR = (0, 0, 0)  # 火柴人黑色

# 创建字体
def create_font(size):
    try:
        font = pygame.font.Font(None, size)
    except:
        font = pygame.font.SysFont("Arial", size)
    return font

# 游戏状态
class Game:
    def __init__(self):
        self.score = 0
        self.high_score = 0
        self.speed = 6
        self.game_over = False
        self.paused = False
        self.ground_y = HEIGHT - 80
        self.font = create_font(36)
        self.big_font = create_font(72)
        self.small_font = create_font(24)
        self.game_time = 0
        self.difficulty_timer = 0
        self.background_offset = 0
        
    def update(self, dt):
        if not self.game_over and not self.paused:
            self.game_time += dt
            self.difficulty_timer += dt
            
            if self.difficulty_timer >= 10000:
                self.speed += 0.5
                self.difficulty_timer = 0
                
            self.background_offset = (self.background_offset - self.speed * 0.5) % WIDTH
    
    def draw_background(self):
        screen.fill(SKY_BLUE)
        
        # 地面
        pygame.draw.rect(screen, GROUND_COLOR, (0, self.ground_y, WIDTH, HEIGHT-self.ground_y))
        
        # 地面细节
        for i in range(-int(self.background_offset) % 50, WIDTH, 50):
            pygame.draw.line(screen, (100, 80, 60), (i, self.ground_y), (i+25, self.ground_y+5), 3)
    
    def draw_score(self):
        score_text = self.font.render(f'分数: {self.score}', True, WHITE)
        screen.blit(score_text, (10, 10))
        
        high_score_text = self.font.render(f'最高分: {self.high_score}', True, WHITE)
        screen.blit(high_score_text, (10, 50))
        
        controls_text = self.small_font.render('空格:跳跃  S:下滑  P:暂停  R:重新开始', True, WHITE)
        screen.blit(controls_text, (WIDTH//2 - 150, HEIGHT - 25))

# 火柴人玩家
class StickMan:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.head_radius = 10
        self.body_height = 25
        self.arm_length = 20
        self.leg_length = 25
        self.jump_power = 15
        self.gravity = 0.8
        self.velocity_y = 0
        self.is_jumping = False
        self.is_sliding = False
        self.slide_timer = 0
        self.jump_count = 0
        self.max_jumps = 2
        self.run_cycle = 0
        self.run_speed = 0.1
        
    def update(self, game):
        self.velocity_y += self.gravity
        self.y += self.velocity_y
        
        if self.y >= game.ground_y - (self.head_radius + self.body_height + self.leg_length):
            self.y = game.ground_y - (self.head_radius + self.body_height + self.leg_length)
            self.velocity_y = 0
            self.is_jumping = False
            self.jump_count = 0
            
            if not self.is_sliding:
                self.run_cycle += self.run_speed
                if self.run_cycle >= 2 * math.pi:
                    self.run_cycle -= 2 * math.pi
            
            if self.is_sliding and self.slide_timer <= 0:
                self.is_sliding = False
        
        if self.is_sliding:
            self.slide_timer -= 1
            if self.slide_timer <= 0:
                self.is_sliding = False
        
        if self.y < 0:
            self.y = 0
            self.velocity_y = 0
    
    def jump(self, game):
        if self.jump_count < self.max_jumps:
            self.velocity_y = -self.jump_power
            self.is_jumping = True
            self.jump_count += 1
            self.run_cycle = 0
            
            if self.is_sliding:
                self.is_sliding = False
    
    def slide(self, game):
        if not self.is_jumping and not self.is_sliding:
            self.is_sliding = True
            self.slide_timer = 30
            self.run_cycle = 0
    
    def get_rect(self):
        head_x = self.x
        head_y = self.y
        width = self.head_radius * 2
        height = self.head_radius * 2 + self.body_height
        
        return pygame.Rect(head_x - width//2, head_y, width, height)
    
    def draw(self, screen):
        head_x = self.x
        head_y = self.y + self.head_radius
        
        body_bottom_x = head_x
        body_bottom_y = head_y + self.head_radius + self.body_height
        
        # 手臂摆动
        if self.is_jumping:
            left_arm_angle = -math.pi/2
            right_arm_angle = -math.pi/2
        elif self.is_sliding:
            left_arm_angle = math.pi * 0.8
            right_arm_angle = math.pi * 0.8
        else:
            left_arm_angle = math.pi/4 + math.sin(self.run_cycle) * math.pi/6
            right_arm_angle = math.pi/4 - math.sin(self.run_cycle) * math.pi/6
        
        # 腿部摆动
        if self.is_jumping:
            left_leg_angle = math.pi/2
            right_leg_angle = math.pi/2
        elif self.is_sliding:
            left_leg_angle = math.pi
            right_leg_angle = math.pi
        else:
            leg_swing = math.sin(self.run_cycle) * math.pi/6
            left_leg_angle = math.pi/2 - leg_swing
            right_leg_angle = math.pi/2 + leg_swing
        
        # 绘制头部
        pygame.draw.circle(screen, BLACK, (int(head_x), int(head_y)), self.head_radius, 2)
        
        # 绘制身体
        pygame.draw.line(screen, BLACK, (head_x, head_y + self.head_radius), 
                        (body_bottom_x, body_bottom_y), 2)
        
        # 绘制手臂
        left_arm_end_x = body_bottom_x + math.cos(left_arm_angle) * self.arm_length
        left_arm_end_y = body_bottom_y + math.sin(left_arm_angle) * self.arm_length
        pygame.draw.line(screen, BLACK, (body_bottom_x, body_bottom_y), 
                        (left_arm_end_x, left_arm_end_y), 2)
        
        right_arm_end_x = body_bottom_x + math.cos(right_arm_angle) * self.arm_length
        right_arm_end_y = body_bottom_y + math.sin(right_arm_angle) * self.arm_length
        pygame.draw.line(screen, BLACK, (body_bottom_x, body_bottom_y), 
                        (right_arm_end_x, right_arm_end_y), 2)
        
        # 绘制腿部
        left_leg_end_x = body_bottom_x + math.cos(left_leg_angle) * self.leg_length
        left_leg_end_y = body_bottom_y + math.sin(left_leg_angle) * self.leg_length
        pygame.draw.line(screen, BLACK, (body_bottom_x, body_bottom_y), 
                        (left_leg_end_x, left_leg_end_y), 2)
        
        right_leg_end_x = body_bottom_x + math.cos(right_leg_angle) * self.leg_length
        right_leg_end_y = body_bottom_y + math.sin(right_leg_angle) * self.leg_length
        pygame.draw.line(screen, BLACK, (body_bottom_x, body_bottom_y), 
                        (right_leg_end_x, right_leg_end_y), 2)
        
        # 绘制眼睛
        eye_radius = 2
        eye_offset = 3
        pygame.draw.circle(screen, BLACK, (int(head_x - eye_offset), int(head_y)), eye_radius)
        pygame.draw.circle(screen, BLACK, (int(head_x + eye_offset), int(head_y)), eye_radius)
        
        # 绘制嘴巴
        if self.is_jumping:
            mouth_rect = pygame.Rect(head_x - 5, head_y + 5, 10, 6)
            pygame.draw.arc(screen, BLACK, mouth_rect, 0, math.pi, 1)
        else:
            pygame.draw.line(screen, BLACK, (head_x - 4, head_y + 5), 
                           (head_x + 4, head_y + 5), 1)

# 障碍物
class Obstacle:
    def __init__(self, x, game):
        self.x = x
        self.game = game
        self.width = random.randint(20, 40)
        self.height = random.randint(30, 50)
        self.color = (100, 100, 100)
        self.passed = False
    
    def update(self):
        self.x -= self.game.speed
        return self.x < -self.width
    
    def get_rect(self):
        return pygame.Rect(self.x, self.game.ground_y - self.height, self.width, self.height)
    
    def draw(self, screen):
        pygame.draw.rect(screen, self.color, self.get_rect())

# 金币
class Coin:
    def __init__(self, x, game):
        self.x = x
        self.y = random.randint(game.ground_y - 120, game.ground_y - 40)
        self.game = game
        self.radius = 10
        self.collected = False
        self.rotation = 0
        
    def update(self):
        self.x -= self.game.speed
        self.rotation += 5
        return self.x < -self.radius * 2
    
    def get_rect(self):
        return pygame.Rect(self.x - self.radius, self.y - self.radius, 
                          self.radius * 2, self.radius * 2)
    
    def draw(self, screen):
        if not self.collected:
            pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), self.radius)
            pygame.draw.circle(screen, (255, 255, 100), (int(self.x), int(self.y)), self.radius//2)

# 主游戏函数
def main():
    game = Game()
    player = StickMan(100, game.ground_y - 60)
    
    obstacles = []
    coins = []
    
    obstacle_timer = 0
    coin_timer = 0
    
    obstacle_interval = 1500
    coin_interval = 1000
    
    running = True
    last_time = pygame.time.get_ticks()
    
    while running:
        current_time = pygame.time.get_ticks()
        dt = current_time - last_time
        last_time = current_time
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    if game.game_over:
                        game = Game()
                        player = StickMan(100, game.ground_y - 60)
                        obstacles = []
                        coins = []
                    else:
                        player.jump(game)
                
                elif event.key == pygame.K_s:
                    if not game.game_over and not game.paused:
                        player.slide(game)
                
                elif event.key == pygame.K_p:
                    game.paused = not game.paused
                
                elif event.key == pygame.K_r:
                    game = Game()
                    player = StickMan(100, game.ground_y - 60)
                    obstacles = []
                    coins = []
        
        if not game.paused and not game.game_over:
            game.update(dt)
            player.update(game)
            
            obstacle_timer += dt
            if obstacle_timer >= obstacle_interval:
                obstacle_timer = 0
                obstacles.append(Obstacle(WIDTH, game))
                obstacle_interval = random.randint(800, 2000)
            
            coin_timer += dt
            if coin_timer >= coin_interval:
                coin_timer = 0
                if random.random() < 0.7:
                    coins.append(Coin(WIDTH, game))
                coin_interval = random.randint(500, 1500)
            
            obstacles_to_remove = []
            for obstacle in obstacles:
                if obstacle.update():
                    obstacles_to_remove.append(obstacle)
                else:
                    if player.get_rect().colliderect(obstacle.get_rect()):
                        game.game_over = True
                    elif not obstacle.passed and obstacle.x < player.x:
                        obstacle.passed = True
                        game.score += 1
                        if game.score > game.high_score:
                            game.high_score = game.score
            
            for obstacle in obstacles_to_remove:
                obstacles.remove(obstacle)
            
            coins_to_remove = []
            for coin in coins:
                if coin.update():
                    coins_to_remove.append(coin)
                elif not coin.collected and player.get_rect().colliderect(coin.get_rect()):
                    coin.collected = True
                    game.score += 5
                    coins_to_remove.append(coin)
            
            for coin in coins_to_remove:
                coins.remove(coin)
        
        game.draw_background()
        
        for coin in coins:
            coin.draw(screen)
        
        for obstacle in obstacles:
            obstacle.draw(screen)
        
        player.draw(screen)
        
        game.draw_score()
        
        if game.game_over:
            overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 128))
            screen.blit(overlay, (0, 0))
            
            game_over_text = game.big_font.render('游戏结束!', True, RED)
            screen.blit(game_over_text, (WIDTH//2 - game_over_text.get_width()//2, HEIGHT//2 - 100))
            
            score_text = game.font.render(f'最终分数: {game.score}', True, WHITE)
            screen.blit(score_text, (WIDTH//2 - score_text.get_width()//2, HEIGHT//2 - 30))
            
            restart_text = game.font.render('按空格键重新开始', True, WHITE)
            screen.blit(restart_text, (WIDTH//2 - restart_text.get_width()//2, HEIGHT//2 + 20))
        
        pygame.display.flip()
        clock.tick(FPS)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()