import pygame
import random
import math

pygame.init()

W, H = 800, 600
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("🏰 Pygame塔防")
clock = pygame.time.Clock()
FPS = 60

# 字体容错（解决你之前的字体报错）
try:
    font = pygame.font.SysFont("simhei", 22)
except:
    font = pygame.font.Font(None, 22)

# 颜色
GRASS = (60, 160, 60)
ROAD = (160, 130, 90)
TOWER = (80, 80, 180)
ENEMY = (200, 40, 40)
BULLET = (255, 220, 0)
TEXT_COLOR = (255,255,255)

# 敌人行走路径点（S路线）
path = [
    (0, 120),
    (200, 120),
    (200, 280),
    (600, 280),
    (600, 420),
    (150, 420),
    (150, 520),
    (800, 520)
]

# 游戏变量
gold = 100
life = 10
tower_cost = 30
game_over = False

# 敌人类
class Enemy:
    def __init__(self):
        self.x, self.y = path[0]
        self.hp = 80
        self.max_hp = 80
        self.speed = 1.2
        self.path_idx = 0
        self.reward = 15

    def update(self):
        # 走向下一个路径点
        if self.path_idx < len(path)-1:
            tx, ty = path[self.path_idx+1]
            dx = tx - self.x
            dy = ty - self.y
            dist = math.hypot(dx, dy)
            if dist < self.speed:
                self.path_idx += 1
            else:
                self.x += dx / dist * self.speed
                self.y += dy / dist * self.speed
        # 到达终点
        if self.path_idx >= len(path)-1:
            return True
        return False

    def draw(self):
        pygame.draw.circle(screen, ENEMY, (int(self.x), int(self.y)), 14)
        # 血条
        bar_w = 24
        pygame.draw.rect(screen, (60,60,60), (self.x-bar_w//2, self.y-22, bar_w, 4))
        hp_ratio = self.hp / self.max_hp
        pygame.draw.rect(screen, (0,220,0), (self.x-bar_w//2, self.y-22, bar_w*hp_ratio, 4))

# 炮塔类
class Tower:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.range = 130
        self.damage = 18
        self.cd = 0
        self.cd_max = 45

    def draw(self):
        pygame.draw.circle(screen, TOWER, (self.x, self.y), 18)
        # 攻击范围圈（淡色）
        pygame.draw.circle(screen, (100,100,220,50), (self.x, self.y), self.range, 1)

    def shoot(self, enemy_list, bullet_list):
        self.cd -= 1
        if self.cd <= 0:
            # 找范围内最近敌人
            target = None
            min_d = self.range
            for e in enemy_list:
                d = math.hypot(e.x - self.x, e.y - self.y)
                if d < min_d:
                    min_d = d
                    target = e
            if target is not None:
                bullet_list.append(Bullet(self.x, self.y, target, self.damage))
                self.cd = self.cd_max

# 子弹类
class Bullet:
    def __init__(self, x, y, target, dmg):
        self.x = x
        self.y = y
        self.target = target
        self.dmg = dmg
        self.speed = 6

    def update(self):
        if self.target.hp <= 0:
            return False
        dx = self.target.x - self.x
        dy = self.target.y - self.y
        dist = math.hypot(dx, dy)
        if dist < 12:
            self.target.hp -= self.dmg
            return False
        self.x += dx / dist * self.speed
        self.y += dy / dist * self.speed
        return True

    def draw(self):
        pygame.draw.circle(screen, BULLET, (int(self.x), int(self.y)), 5)

enemies = []
towers = []
bullets = []
spawn_timer = 0

running = True
while running:
    screen.fill(GRASS)
    # 画路径
    for i in range(len(path)-1):
        pygame.draw.line(screen, ROAD, path[i], path[i+1], 36)

    dt = clock.tick(FPS)
    spawn_timer += 1
    # 生成敌人
    if spawn_timer > 120 and not game_over:
        enemies.append(Enemy())
        spawn_timer = 0

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        # 鼠标点击放炮塔
        if event.type == pygame.MOUSEBUTTONDOWN and not game_over:
            mx, my = event.pos
            # 简单判断：不在路径上
            on_road = False
            for i in range(len(path)-1):
                x1,y1 = path[i]
                x2,y2 = path[i+1]
                # 粗略判断是否在路附近
                A = mx - x1
                B = my - y1
                C = x2 - x1
                D = y2 - y1
                dot = A*C + B*D
                len_sq = C*C + D*D
                if len_sq ==0:
                    continue
                t = max(0, min(1, dot / len_sq))
                proj_x = x1 + t * C
                proj_y = y1 + t * D
                dist = math.hypot(mx-proj_x, my-proj_y)
                if dist < 22:
                    on_road = True
                    break
            if not on_road and gold >= tower_cost:
                towers.append(Tower(mx, my))
                gold -= tower_cost

    if not game_over:
        # 更新敌人
        for e in enemies[:]:
            arrive = e.update()
            if arrive:
                life -= 1
                enemies.remove(e)
            elif e.hp <= 0:
                gold += e.reward
                enemies.remove(e)
        # 炮塔攻击
        for t in towers:
            t.shoot(enemies, bullets)
        # 更新子弹
        for b in bullets[:]:
            alive = b.update()
            if not alive:
                bullets.remove(b)

        if life <= 0:
            game_over = True

    # 绘制
    for t in towers:
        t.draw()
    for e in enemies:
        e.draw()
    for b in bullets:
        b.draw()

    # UI
    gold_text = font.render(f"金币：{gold}", True, TEXT_COLOR)
    life_text = font.render(f"生命：{life}", True, TEXT_COLOR)
    tip = font.render(f"点击草地放置炮塔({tower_cost}金)，不能放在路上", True, TEXT_COLOR)
    screen.blit(gold_text, (10, 10))
    screen.blit(life_text, (10, 36))
    screen.blit(tip, (10, 62))

    if game_over:
        over_text = font.render("游戏结束！敌人突破防线！", True, (255,0,0))
        screen.blit(over_text, (W//2 - 140, H//2))

    pygame.display.flip()

pygame.quit()
