import pygame
import random
import sys

pygame.init()

WIDTH, HEIGHT = 1000, 550
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("跑酷游戏")
clock = pygame.time.Clock()
FPS = 60

BG_TOP = (135, 206, 235)
BG_BOT = (240, 248, 255)
GROUND_COLOR = (72, 126, 62)
PLAYER_COLOR = (41, 128, 185)
OBSTACLE_COLOR = (192, 57, 43)
COIN_COLOR = (241, 196, 15)
CLOUD_COLOR = (255, 255, 255)

gravity = 0.9
jump_power = -18
double_jump_power = -15
game_speed = 8
max_speed = 18

class Player:
    def __init__(self):
        self.x = 100
        self.y = HEIGHT - 130
        self.w = 45
        self.h = 70
        self.vy = 0
        self.jump_count = 0

    def jump(self):
        if self.jump_count < 2:
            if self.jump_count == 0:
                self.vy = jump_power
            else:
                self.vy = double_jump_power
            self.jump_count += 1

    def update(self):
        self.vy += gravity
        self.y += self.vy
        ground_y = HEIGHT - 60 - self.h
        if self.y >= ground_y:
            self.y = ground_y
            self.vy = 0
            self.jump_count = 0

    def draw(self):
        pygame.draw.rect(screen, PLAYER_COLOR, (self.x, self.y, self.w, self.h), border_radius=12)

class Obstacle:
    def __init__(self):
        self.w = random.randint(35, 55)
        self.h = random.randint(55, 85)
        self.x = WIDTH
        self.y = HEIGHT - 60 - self.h

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

    def draw(self):
        pygame.draw.rect(screen, OBSTACLE_COLOR, (self.x, self.y, self.w, self.h), border_radius=8)

class Coin:
    def __init__(self):
        self.r = 12
        self.x = WIDTH
        self.y = random.randint(HEIGHT-180, HEIGHT-90)

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

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

class Cloud:
    def __init__(self):
        self.x = random.randint(0, WIDTH)
        self.y = random.randint(30, 180)
        self.size = random.randint(40, 90)
        self.speed = random.uniform(0.4, 1.2)

    def update(self):
        self.x -= self.speed
        if self.x < -self.size:
            self.x = WIDTH + self.size

    def draw(self):
        pygame.draw.ellipse(screen, CLOUD_COLOR, (self.x, self.y, self.size, self.size//2))

class Ground:
    def __init__(self):
        self.x1 = 0
        self.x2 = WIDTH
        self.y = HEIGHT - 60

    def update(self, speed):
        self.x1 -= speed
        self.x2 -= speed
        if self.x1 <= -WIDTH:
            self.x1 = WIDTH
        if self.x2 <= -WIDTH:
            self.x2 = WIDTH

    def draw(self):
        pygame.draw.rect(screen, GROUND_COLOR, (self.x1, self.y, WIDTH, 20))
        pygame.draw.rect(screen, GROUND_COLOR, (self.x2, self.y, WIDTH, 20))

def draw_bg():
    for y in range(HEIGHT):
        ratio = y / HEIGHT
        r = int(BG_TOP[0] * (1-ratio) + BG_BOT[0] * ratio)
        g = int(BG_TOP[1] * (1-ratio) + BG_BOT[1] * ratio)
        b = int(BG_TOP[2] * (1-ratio) + BG_BOT[2] * ratio)
        pygame.draw.line(screen, (r,g,b), (0,y), (WIDTH,y))

def main():
    player = Player()
    ground = Ground()
    clouds = [Cloud() for _ in range(6)]
    obstacles = []
    coins = []

    game_over = False
    spawn_cd = 0
    coin_cd = 0
    speed = game_speed

    while True:
        draw_bg()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if not game_over:
                    if event.key == pygame.K_SPACE:
                        player.jump()
                else:
                    if event.key == pygame.K_SPACE:
                        main()

        if not game_over:
            speed = min(max_speed, game_speed)
            player.update()
            ground.update(speed)
            
            for c in clouds:
                c.update()

            spawn_cd += 1
            if spawn_cd > random.randint(50, 90):
                obstacles.append(Obstacle())
                spawn_cd = 0

            coin_cd += 1
            if coin_cd > 35:
                coins.append(Coin())
                coin_cd = 0

            for o in obstacles[:]:
                o.update(speed)
                if o.x + o.w < 0:
                    obstacles.remove(o)

            for c in coins[:]:
                c.update(speed)
                if c.x < -20:
                    coins.remove(c)
                p_rect = pygame.Rect(player.x, player.y, player.w, player.h)
                if p_rect.collidepoint(c.x, c.y):
                    coins.remove(c)

            p_rect = pygame.Rect(player.x, player.y, player.w, player.h)
            for o in obstacles:
                o_rect = pygame.Rect(o.x, o.y, o.w, o.h)
                if p_rect.colliderect(o_rect):
                    game_over = True

        for c in clouds:
            c.draw()
        ground.draw()
        for o in obstacles:
            o.draw()
        for c in coins:
            c.draw()
        player.draw()

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

if __name__ == "__main__":
    main()