import pygame
import random
import sys

pygame.init()
WIDTH = 800
HEIGHT = 480
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Chicken Run Shooter")

# Colors
SKY = (115, 185, 245)
GROUND = (90, 160, 50)
GROUND_DARK = (65, 110, 35)
CHICKEN_BODY = (255, 220, 40)
CHICKEN_OUT = (200, 140, 0)
BEAK = (255, 130, 0)
STONE = (100, 100, 110)
STONE_DARK = (60, 60, 70)
BARRIER_YELLOW = (255, 210, 0)
BARRIER_BLACK = (20, 20, 20)
TREE_GREEN = (35, 130, 30)
TREE_TRUNK = (110,70,40)
HOUSE_WALL = (230,110,60)
HOUSE_ROOF = (160,40,40)
BUSH_GREEN = (50,150,40)
ENEMY_COLOR = (160, 30, 30)
BOSS_COLOR = (70,20,70)
BULLET_COLOR = (255,255,60)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (220, 30, 30)
GOLD = (255, 215, 0)

# Font
font_big = pygame.font.Font(None, 48)
font_mid = pygame.font.Font(None, 36)
font_small = pygame.font.Font(None, 28)

# Chicken
cw = 36
ch = 42
cx = 120
cy = HEIGHT - 100
vy = 0
gravity = 0.62
jump_power = -14
on_ground = True
gun_cooldown = 0
COOLDOWN_TIME = 180

# Game variable
obstacles = []
enemies = []
bullets = []
boss = None
obstacle_speed = 5
spawn_timer = 0
spawn_gap = 1300
score = 0
high_score = 0
game_over = False
win_game = False
clock = pygame.time.Clock()

# Background scenery
scenery_list = []

def reset_game():
    global cx, cy, vy, on_ground, obstacles, enemies, bullets, boss
    global score, game_over, win_game, spawn_timer, obstacle_speed, scenery_list, gun_cooldown
    cx = 120
    cy = HEIGHT - 100
    vy = 0
    on_ground = True
    gun_cooldown = 0
    obstacles.clear()
    enemies.clear()
    bullets.clear()
    boss = None
    scenery_list.clear()
    score = 0
    game_over = False
    win_game = False
    spawn_timer = 0
    obstacle_speed = 5
    for i in range(6):
        item_type = random.choice(["tree","house","bush"])
        scenery_list.append({
            "x": random.randint(0, WIDTH),
            "type": item_type
        })

reset_game()

def draw_scenery(item):
    sx = item["x"]
    ground_y = HEIGHT - 60
    if item["type"] == "tree":
        pygame.draw.rect(screen, TREE_TRUNK, (sx+16, ground_y-60, 14, 60))
        pygame.draw.circle(screen, TREE_GREEN, (sx+23, ground_y-75), 32)
    elif item["type"] == "house":
        pygame.draw.rect(screen, HOUSE_WALL, (sx, ground_y-55, 55, 55))
        pygame.draw.polygon(screen, HOUSE_ROOF, [
            (sx-6, ground_y-55),
            (sx+28, ground_y-90),
            (sx+62, ground_y-55)
        ])
    elif item["type"] == "bush":
        pygame.draw.circle(screen, BUSH_GREEN, (sx+18, ground_y-22), 20)

running = True
while running:
    dt = clock.tick(60)
    spawn_timer += dt
    gun_cooldown -= dt
    screen.fill(SKY)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_r:
                reset_game()
            if not game_over and not win_game:
                # 上方向键跳跃
                if event.key == pygame.K_UP and on_ground:
                    vy = jump_power
                # 空格发射子弹
                if event.key == pygame.K_SPACE:
                    if gun_cooldown <= 0:
                        bullets.append({"x": cx + cw, "y": cy + ch//2, "speed": 10})
                        gun_cooldown = COOLDOWN_TIME

    if not game_over and not win_game:
        # Chicken physics
        vy += gravity
        cy += vy
        chicken_rect = pygame.Rect(cx, cy, cw, ch)
        ground_y = HEIGHT - 60

        if cy + ch >= ground_y:
            cy = ground_y - ch
            vy = 0
            on_ground = True
        else:
            on_ground = False

        # Spawn obstacles and enemies, no spawn when boss active
        if boss is None:
            if spawn_timer > spawn_gap:
                rand_type = random.random()
                if rand_type < 0.35:
                    obs_type = "stone"
                    obs_w = random.randint(32, 52)
                    obs_h = random.randint(36, 56)
                    obstacles.append({
                        "x": WIDTH, "y": ground_y - obs_h,
                        "w": obs_w, "h": obs_h, "kind": obs_type
                    })
                elif rand_type < 0.65:
                    obs_type = "barrier"
                    obstacles.append({
                        "x": WIDTH, "y": ground_y - 44,
                        "w": 38, "h": 44, "kind": obs_type
                    })
                else:
                    enemies.append({
                        "x": WIDTH, "y": ground_y - 38,
                        "w": 34, "h": 38, "hp": 1
                    })
                spawn_timer = 0
                spawn_gap = max(700, spawn_gap - 15)
                obstacle_speed += 0.06

        # Trigger boss when score >= 15
        if boss is None and score >= 15:
            boss = {
                "x": WIDTH - 120, "y": ground_y - 72,
                "w": 70, "h":72, "hp":8, "dir":-1
            }

        # Update bullets
        for blt in bullets[:]:
            blt["x"] += blt["speed"]
            if blt["x"] > WIDTH:
                bullets.remove(blt)

        # Update obstacles
        for obs in obstacles[:]:
            obs["x"] -= obstacle_speed
            obs_rect = pygame.Rect(obs["x"], obs["y"], obs["w"], obs["h"])
            if chicken_rect.colliderect(obs_rect):
                game_over = True
                if score > high_score:
                    high_score = score
            if obs["x"] + obs["w"] < 0:
                obstacles.remove(obs)
                score += 1

        # Update enemies
        for enemy in enemies[:]:
            enemy["x"] -= obstacle_speed
            e_rect = pygame.Rect(enemy["x"], enemy["y"], enemy["w"], enemy["h"])
            if chicken_rect.colliderect(e_rect):
                game_over = True
                if score > high_score:
                    high_score = score
            # Bullet hit enemy
            hit = False
            for blt in bullets[:]:
                blt_rect = pygame.Rect(blt["x"], blt["y"], 10, 5)
                if blt_rect.colliderect(e_rect):
                    enemy["hp"] -=1
                    bullets.remove(blt)
                    hit = True
                    if enemy["hp"] <= 0:
                        enemies.remove(enemy)
                        score +=2
                    break
            if enemy["x"] + enemy["w"] < 0:
                enemies.remove(enemy)

        # Boss logic
        if boss is not None:
            boss["x"] += boss["dir"] * 1.8
            if boss["x"] < WIDTH//2 or boss["x"] > WIDTH - 90:
                boss["dir"] *= -1
            boss_rect = pygame.Rect(boss["x"], boss["y"], boss["w"], boss["h"])
            if chicken_rect.colliderect(boss_rect):
                game_over = True
                if score > high_score:
                    high_score = score
            # Bullet hit boss
            for blt in bullets[:]:
                blt_rect = pygame.Rect(blt["x"], blt["y"], 10, 5)
                if blt_rect.colliderect(boss_rect):
                    boss["hp"] -=1
                    bullets.remove(blt)
                    if boss["hp"] <= 0:
                        win_game = True
                    break

        # Scroll background
        for s in scenery_list:
            s["x"] -= obstacle_speed * 0.35
            if s["x"] < -80:
                s["x"] = WIDTH + random.randint(30,120)
                s["type"] = random.choice(["tree","house","bush"])

    # Draw background
    for sc in scenery_list:
        draw_scenery(sc)

    # Ground
    pygame.draw.rect(screen, GROUND_DARK, (0, HEIGHT - 60, WIDTH, 60))
    pygame.draw.rect(screen, GROUND, (0, HEIGHT - 60, WIDTH, 10))

    # Obstacles
    for obs in obstacles:
        x, y, w, h = obs["x"], obs["y"], obs["w"], obs["h"]
        if obs["kind"] == "stone":
            pygame.draw.rect(screen, STONE_DARK, (x+3, y+3, w, h), border_radius=4)
            pygame.draw.rect(screen, STONE, (x, y, w, h), border_radius=4)
        elif obs["kind"] == "barrier":
            p1 = (x, y+h)
            p2 = (x + w//2, y)
            p3 = (x + w, y+h)
            pygame.draw.polygon(screen, BARRIER_YELLOW, [p1,p2,p3])
            pygame.draw.line(screen, BARRIER_BLACK, p1,p2,3)
            pygame.draw.line(screen, BARRIER_BLACK, p2,p3,3)

    # Draw enemies
    for enemy in enemies:
        x,y,w,h = enemy["x"], enemy["y"], enemy["w"], enemy["h"]
        pygame.draw.rect(screen, ENEMY_COLOR, (x,y,w,h), border_radius=6)
        pygame.draw.circle(screen, WHITE, (x+8, y+10), 3)
        pygame.draw.circle(screen, WHITE, (x+24, y+10), 3)

    # Draw boss
    if boss is not None:
        x,y,w,h = boss["x"], boss["y"], boss["w"], boss["h"]
        pygame.draw.rect(screen, BOSS_COLOR, (x,y,w,h), border_radius=10)
        pygame.draw.rect(screen, BLACK, (x,y,w,h),3,border_radius=10)
        pygame.draw.circle(screen, RED, (x+18, y+18),6)
        pygame.draw.circle(screen, RED, (x+52, y+18),6)
        hp_text = font_small.render(f"HP:{boss['hp']}",True,WHITE)
        screen.blit(hp_text,(x+12,y-28))

    # Draw bullets
    for blt in bullets:
        pygame.draw.rect(screen, BULLET_COLOR, (blt["x"], blt["y"], 10, 5), border_radius=2)

    # Draw chicken
    pygame.draw.rect(screen, CHICKEN_BODY, (cx, cy, cw, ch), border_radius=10)
    pygame.draw.rect(screen, CHICKEN_OUT, (cx, cy, cw, ch), 2, border_radius=10)
    pygame.draw.circle(screen, WHITE, (cx + 26, cy + 12), 5)
    pygame.draw.circle(screen, BLACK, (cx + 27, cy + 13), 2)
    pygame.draw.polygon(screen, BEAK, [(cx+32, cy+18), (cx+44, cy+22), (cx+32, cy+26)])
    # Draw pistol
    pygame.draw.rect(screen, (60,60,60), (cx+30, cy+22, 18,7), border_radius=2)

    # UI
    score_text = font_mid.render(f"Score: {score}", True, WHITE)
    best_text = font_mid.render(f"Best: {high_score}", True, GOLD)
    screen.blit(score_text, (12, 10))
    screen.blit(best_text, (12, 42))
    hint_text = font_small.render("UP=Jump | SPACE=Shoot | R=Restart", True, WHITE)
    screen.blit(hint_text, (12,70))

    if game_over:
        overlay = pygame.Surface((WIDTH, HEIGHT))
        overlay.set_alpha(140)
        overlay.fill(BLACK)
        screen.blit(overlay, (0,0))
        text1 = font_big.render("Game Over!", True, RED)
        text2 = font_mid.render("Press R to restart", True, WHITE)
        screen.blit(text1, text1.get_rect(center=(WIDTH//2, HEIGHT//2 - 40)))
        screen.blit(text2, text2.get_rect(center=(WIDTH//2, HEIGHT//2 + 20)))
    if win_game:
        overlay = pygame.Surface((WIDTH, HEIGHT))
        overlay.set_alpha(140)
        overlay.fill(BLACK)
        screen.blit(overlay, (0,0))
        text1 = font_big.render("You Defeated Boss! Victory!", True, GOLD)
        text2 = font_mid.render("Press R to restart", True, WHITE)
        screen.blit(text1, text1.get_rect(center=(WIDTH//2, HEIGHT//2 - 40)))
        screen.blit(text2, text2.get_rect(center=(WIDTH//2, HEIGHT//2 + 20)))

    pygame.display.update()

pygame.quit()
sys.exit()