import pygame
import random
import sys
import math
import time

# 初始化pygame
pygame.init()

# 游戏设置
WIDTH, HEIGHT = 1000, 700
FPS = 60
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("植物大战僵尸")
clock = pygame.time.Clock()

# 颜色定义
GREEN = (50, 200, 50)
DARK_GREEN = (20, 100, 20)
BROWN = (139, 69, 19)
LIGHT_BROWN = (222, 184, 135)
BLUE = (30, 144, 255)
RED = (255, 50, 50)
YELLOW = (255, 215, 0)
PURPLE = (180, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
LIGHT_GREEN = (144, 238, 144)
GREEN_BG = (100, 150, 100)
SKY_BLUE = (135, 206, 235)

# 草坪设置
LAWN_ROWS = 5
LAWN_COLS = 9
LAWN_WIDTH = 80
LAWN_HEIGHT = 100
LAWN_START_X = 200
LAWN_START_Y = 100

# 植物类型


class PlantType:
    SUNFLOWER = 0
    PEA_SHOOTER = 1
    WALL_NUT = 2
    SNOW_PEA = 3

# 植物基类


class Plant:
    def __init__(self, x, y, plant_type):
        self.x = x
        self.y = y
        self.type = plant_type
        self.health = 100
        self.max_health = 100
        self.attack_timer = 0
        self.animation_timer = 0

        # 不同类型植物的属性
        if plant_type == PlantType.SUNFLOWER:
            self.cost = 50
            self.sun_timer = 0
            self.color = YELLOW
        elif plant_type == PlantType.PEA_SHOOTER:
            self.cost = 100
            self.attack_speed = 60  # 每60帧发射一次
            self.color = GREEN
        elif plant_type == PlantType.WALL_NUT:
            self.cost = 50
            self.health = 300
            self.max_health = 300
            self.color = BROWN
        elif plant_type == PlantType.SNOW_PEA:
            self.cost = 175
            self.attack_speed = 80
            self.color = (200, 200, 255)

    def draw(self, screen):
        # 绘制植物底座
        pygame.draw.rect(screen, DARK_GREEN,
                         (self.x, self.y, LAWN_WIDTH, LAWN_HEIGHT), 1)

        # 绘制植物主体
        if self.type == PlantType.SUNFLOWER:
            # 向日葵
            pygame.draw.circle(screen, self.color,
                               (self.x + LAWN_WIDTH//2, self.y + LAWN_HEIGHT//2), 25)
            pygame.draw.circle(screen, BROWN,
                               (self.x + LAWN_WIDTH//2, self.y + LAWN_HEIGHT//2), 15)

            # 动画效果
            for i in range(8):
                angle = self.animation_timer + i * 45
                rad = math.radians(angle)
                px = self.x + LAWN_WIDTH//2 + math.cos(rad) * 35
                py = self.y + LAWN_HEIGHT//2 + math.sin(rad) * 35
                pygame.draw.circle(screen, YELLOW, (int(px), int(py)), 10)

        elif self.type == PlantType.PEA_SHOOTER:
            # 豌豆射手
            pygame.draw.rect(screen, self.color,
                             (self.x + 20, self.y + 20, 40, 60))
            pygame.draw.circle(screen, DARK_GREEN,
                               (self.x + LAWN_WIDTH//2, self.y + 30), 15)
            # 枪管
            pygame.draw.rect(screen, (0, 100, 0),
                             (self.x + LAWN_WIDTH - 20, self.y + LAWN_HEIGHT//2 - 5, 20, 10))

        elif self.type == PlantType.WALL_NUT:
            # 坚果墙
            pygame.draw.circle(screen, self.color,
                               (self.x + LAWN_WIDTH//2, self.y + LAWN_HEIGHT//2), 35)
            # 坚果表情
            pygame.draw.circle(screen, BLACK,
                               (self.x + LAWN_WIDTH//2 - 10, self.y + LAWN_HEIGHT//2 - 5), 3)
            pygame.draw.circle(screen, BLACK,
                               (self.x + LAWN_WIDTH//2 + 10, self.y + LAWN_HEIGHT//2 - 5), 3)
            pygame.draw.arc(screen, BLACK,
                            (self.x + LAWN_WIDTH//2 - 10,
                             self.y + LAWN_HEIGHT//2 + 5, 20, 10),
                            math.pi, 2*math.pi, 2)

        elif self.type == PlantType.SNOW_PEA:
            # 寒冰射手
            pygame.draw.rect(screen, self.color,
                             (self.x + 20, self.y + 20, 40, 60))
            pygame.draw.circle(screen, (150, 150, 255),
                               (self.x + LAWN_WIDTH//2, self.y + 30), 15)
            # 冰枪管
            pygame.draw.rect(screen, (200, 220, 255),
                             (self.x + LAWN_WIDTH - 20, self.y + LAWN_HEIGHT//2 - 5, 20, 10))

        # 绘制生命条
        if self.health < self.max_health:
            bar_width = 60
            bar_height = 5
            health_percent = self.health / self.max_health
            pygame.draw.rect(screen, RED,
                             (self.x + 10, self.y - 10, bar_width, bar_height))
            pygame.draw.rect(screen, GREEN,
                             (self.x + 10, self.y - 10, bar_width * health_percent, bar_height))

    def update(self, projectiles, zombies, suns):
        self.animation_timer = (self.animation_timer + 2) % 360

        if self.type == PlantType.SUNFLOWER:
            # 向日葵产生阳光
            self.sun_timer += 1
            if self.sun_timer >= 300:  # 每5秒产生一个阳光
                suns.append(Sun(self.x + LAWN_WIDTH//2, self.y))
                self.sun_timer = 0

        elif self.type in [PlantType.PEA_SHOOTER, PlantType.SNOW_PEA]:
            # 发射子弹
            self.attack_timer += 1
            if self.attack_timer >= self.attack_speed:
                # 检查前方是否有僵尸
                for zombie in zombies:
                    if (zombie.row == (self.y - LAWN_START_Y) // LAWN_HEIGHT and
                            zombie.x > self.x):
                        # 发射子弹
                        damage = 20
                        speed = 5
                        is_slow = (self.type == PlantType.SNOW_PEA)
                        projectiles.append(
                            Projectile(self.x + LAWN_WIDTH,
                                       self.y + LAWN_HEIGHT//2,
                                       damage, speed, is_slow)
                        )
                        self.attack_timer = 0
                        break

    def get_rect(self):
        return pygame.Rect(self.x, self.y, LAWN_WIDTH, LAWN_HEIGHT)

# 僵尸类


class Zombie:
    def __init__(self, row):
        self.row = row
        self.x = WIDTH
        self.y = LAWN_START_Y + row * LAWN_HEIGHT + LAWN_HEIGHT//2
        self.speed = 0.5
        self.health = 100
        self.max_health = 100
        self.damage = 10
        self.attack_timer = 0
        self.is_slowed = False
        self.slow_timer = 0
        self.animation_timer = 0
        self.color = random.choice([(0, 150, 0), (0, 100, 0), (50, 150, 50)])

    def draw(self, screen):
        # 僵尸身体
        pygame.draw.rect(screen, self.color,
                         (self.x - 20, self.y - 40, 40, 60))

        # 僵尸头部
        pygame.draw.circle(screen, (200, 150, 100),
                           (self.x, self.y - 50), 20)

        # 眼睛
        pygame.draw.circle(screen, BLACK, (self.x - 8, self.y - 55), 4)
        pygame.draw.circle(screen, BLACK, (self.x + 8, self.y - 55), 4)

        # 嘴巴
        pygame.draw.arc(screen, BLACK,
                        (self.x - 10, self.y - 45, 20, 15),
                        0, math.pi, 2)

        # 手臂
        arm_y_offset = math.sin(self.animation_timer) * 5
        pygame.draw.line(screen, self.color,
                         (self.x - 20, self.y - 20),
                         (self.x - 40, self.y - 20 + arm_y_offset), 6)
        pygame.draw.line(screen, self.color,
                         (self.x + 20, self.y - 20),
                         (self.x + 40, self.y - 20 - arm_y_offset), 6)

        # 生命条
        if self.health < self.max_health:
            bar_width = 40
            bar_height = 4
            health_percent = self.health / self.max_health
            pygame.draw.rect(screen, RED,
                             (self.x - 20, self.y - 70, bar_width, bar_height))
            pygame.draw.rect(screen, GREEN,
                             (self.x - 20, self.y - 70, bar_width * health_percent, bar_height))

        # 减速效果
        if self.is_slowed:
            pygame.draw.circle(screen, (150, 200, 255),
                               (self.x, self.y - 60), 8, 2)

    def update(self, plants, zombies, game):
        self.animation_timer += 0.1

        # 更新减速状态
        if self.is_slowed:
            self.slow_timer -= 1
            if self.slow_timer <= 0:
                self.is_slowed = False
                self.speed = 0.5

        # 计算实际速度
        current_speed = self.speed * 0.5 if self.is_slowed else self.speed

        # 检查前方是否有植物
        target_plant = None
        for plant in plants:
            plant_rect = plant.get_rect()
            if (plant.y == LAWN_START_Y + self.row * LAWN_HEIGHT and
                    plant.x < self.x < plant.x + LAWN_WIDTH + 10):
                target_plant = plant
                break

        if target_plant:
            # 攻击植物
            self.attack_timer += 1
            if self.attack_timer >= 60:  # 每秒攻击一次
                target_plant.health -= self.damage
                if target_plant.health <= 0:
                    plants.remove(target_plant)
                self.attack_timer = 0
        else:
            # 向前移动
            self.x -= current_speed

            # 检查是否到达房子
            if self.x < LAWN_START_X - 50:
                game.game_over = True

        # 更新位置
        self.y = LAWN_START_Y + self.row * LAWN_HEIGHT + LAWN_HEIGHT//2

    def get_rect(self):
        return pygame.Rect(self.x - 20, self.y - 50, 40, 60)

# 子弹类


class Projectile:
    def __init__(self, x, y, damage, speed, is_slow=False):
        self.x = x
        self.y = y
        self.damage = damage
        self.speed = speed
        self.is_slow = is_slow
        self.radius = 5

    def draw(self, screen):
        if self.is_slow:
            pygame.draw.circle(screen, (150, 200, 255),
                               (int(self.x), int(self.y)), self.radius)
            pygame.draw.circle(screen, (200, 220, 255),
                               (int(self.x), int(self.y)), self.radius-2)
        else:
            pygame.draw.circle(
                screen, GREEN, (int(self.x), int(self.y)), self.radius)
            pygame.draw.circle(screen, LIGHT_GREEN,
                               (int(self.x), int(self.y)), self.radius-2)

    def update(self, zombies):
        self.x += self.speed

        # 检查是否击中僵尸
        for zombie in zombies:
            if (abs(self.x - zombie.x) < 20 and
                    abs(self.y - zombie.y) < 30):
                zombie.health -= self.damage
                if self.is_slow:
                    zombie.is_slowed = True
                    zombie.slow_timer = 180  # 3秒减速
                    zombie.speed = 0.5 * 0.3  # 减慢70%
                return True  # 击中

        # 超出屏幕
        return self.x > WIDTH

# 阳光类


class Sun:
    def __init__(self, x, y, falling=True):
        self.x = x
        self.y = y
        self.falling = falling
        self.fall_speed = 1
        self.value = 25
        self.timer = 600  # 10秒后消失
        self.animation = 0

    def draw(self, screen):
        self.animation = (self.animation + 5) % 360

        # 绘制阳光
        pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), 15)

        # 绘制光芒
        for i in range(8):
            angle = self.animation + i * 45
            rad = math.radians(angle)
            px = self.x + math.cos(rad) * 25
            py = self.y + math.sin(rad) * 25
            pygame.draw.line(screen, YELLOW,
                             (self.x, self.y), (px, py), 3)

    def update(self):
        if self.falling:
            self.y += self.fall_speed
            if self.y > LAWN_START_Y + LAWN_HEIGHT * 5:
                self.falling = False

        self.timer -= 1
        return self.timer <= 0

    def get_rect(self):
        return pygame.Rect(self.x - 20, self.y - 20, 40, 40)

# 游戏主类


class Game:
    def __init__(self):
        self.sun = 200
        self.plants = []
        self.zombies = []
        self.projectiles = []
        self.suns = []
        self.wave = 1
        self.wave_timer = 600  # 10秒后第一波
        self.zombie_spawn_timer = 0
        self.game_over = False
        self.victory = False
        self.selected_plant = None
        self.font = pygame.font.Font(None, 36)
        self.small_font = pygame.font.Font(None, 24)
        self.big_font = pygame.font.Font(None, 72)

        # 生成初始阳光
        for _ in range(5):
            self.suns.append(
                Sun(random.randint(LAWN_START_X, WIDTH - 100),
                    random.randint(LAWN_START_Y, LAWN_START_Y + LAWN_HEIGHT * 5))
            )

    def draw_lawn(self, screen):
        # 绘制草坪背景
        pygame.draw.rect(screen, GREEN_BG, (0, 0, WIDTH, HEIGHT))

        # 绘制草坪格子
        for row in range(LAWN_ROWS):
            for col in range(LAWN_COLS):
                x = LAWN_START_X + col * LAWN_WIDTH
                y = LAWN_START_Y + row * LAWN_HEIGHT

                # 草坪格子
                pygame.draw.rect(
                    screen, GREEN, (x, y, LAWN_WIDTH, LAWN_HEIGHT), 1)

                # 草坪内部
                pygame.draw.rect(screen, LIGHT_GREEN,
                                 (x + 1, y + 1, LAWN_WIDTH - 2, LAWN_HEIGHT - 2))

        # 绘制房子
        pygame.draw.rect(screen, BROWN,
                         (LAWN_START_X - 100, LAWN_START_Y, 80, LAWN_HEIGHT * LAWN_ROWS))
        pygame.draw.polygon(screen, RED, [
            (LAWN_START_X - 100, LAWN_START_Y),
            (LAWN_START_X - 20, LAWN_START_Y),
            (LAWN_START_X - 60, LAWN_START_Y - 40)
        ])

        # 绘制房子窗户
        for i in range(LAWN_ROWS):
            window_y = LAWN_START_Y + i * LAWN_HEIGHT + LAWN_HEIGHT//2 - 15
            pygame.draw.rect(screen, SKY_BLUE,
                             (LAWN_START_X - 85, window_y, 30, 30))
            pygame.draw.rect(screen, BLACK,
                             (LAWN_START_X - 85, window_y, 30, 30), 2)
            pygame.draw.line(screen, BLACK,
                             (LAWN_START_X - 85, window_y + 15),
                             (LAWN_START_X - 55, window_y + 15), 2)
            pygame.draw.line(screen, BLACK,
                             (LAWN_START_X - 70, window_y),
                             (LAWN_START_X - 70, window_y + 30), 2)

    def draw_ui(self, screen):
        # 绘制UI背景
        pygame.draw.rect(screen, (50, 50, 100), (0, 0, WIDTH, 80))
        pygame.draw.rect(screen, (70, 70, 120), (0, 80, WIDTH, 20))

        # 显示阳光数量
        sun_text = self.font.render(f"阳光: {self.sun}", True, YELLOW)
        screen.blit(sun_text, (20, 20))

        # 显示波数
        wave_text = self.font.render(f"波数: {self.wave}", True, WHITE)
        screen.blit(wave_text, (200, 20))

        # 植物卡片
        plant_types = [
            ("向日葵", 50, YELLOW, PlantType.SUNFLOWER),
            ("豌豆射手", 100, GREEN, PlantType.PEA_SHOOTER),
            ("坚果墙", 50, BROWN, PlantType.WALL_NUT),
            ("寒冰射手", 175, (200, 200, 255), PlantType.SNOW_PEA)
        ]

        for i, (name, cost, color, plant_type) in enumerate(plant_types):
            card_x = 400 + i * 120
            card_y = 20

            # 卡片背景
            card_color = color if self.sun >= cost else GRAY
            pygame.draw.rect(screen, card_color,
                             (card_x, card_y, 100, 60), border_radius=5)
            pygame.draw.rect(screen, BLACK, (card_x, card_y,
                             100, 60), 2, border_radius=5)

            # 植物名称
            name_text = self.small_font.render(name, True, BLACK)
            screen.blit(name_text, (card_x + 10, card_y + 5))

            # 植物价格
            cost_text = self.font.render(str(cost), True, YELLOW)
            screen.blit(cost_text, (card_x + 40, card_y + 30))

            # 阳光图标
            pygame.draw.circle(screen, YELLOW, (card_x + 20, card_y + 40), 8)

        # 游戏说明
        help_text = self.small_font.render("点击植物卡片选择，然后点击草坪种植", True, WHITE)
        screen.blit(help_text, (WIDTH - 300, 20))

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.selected_plant = None
                elif event.key == pygame.K_r and (self.game_over or self.victory):
                    self.__init__()  # 重新开始
                elif event.key == pygame.K_SPACE:
                    # 快速添加阳光（调试用）
                    self.sun += 100

            elif event.type == pygame.MOUSEBUTTONDOWN:
                x, y = event.pos

                # 检查是否点击了植物卡片
                plant_types = [
                    (PlantType.SUNFLOWER, 50),
                    (PlantType.PEA_SHOOTER, 100),
                    (PlantType.WALL_NUT, 50),
                    (PlantType.SNOW_PEA, 175)
                ]

                for i, (plant_type, cost) in enumerate(plant_types):
                    card_x = 400 + i * 120
                    card_y = 20

                    if (card_x <= x <= card_x + 100 and
                        card_y <= y <= card_y + 60 and
                            self.sun >= cost):
                        self.selected_plant = (plant_type, cost)
                        break

                # 检查是否点击了草坪
                if (LAWN_START_X <= x <= LAWN_START_X + LAWN_WIDTH * LAWN_COLS and
                        LAWN_START_Y <= y <= LAWN_START_Y + LAWN_HEIGHT * LAWN_ROWS):

                    if self.selected_plant:
                        plant_type, cost = self.selected_plant

                        # 计算网格位置
                        col = (x - LAWN_START_X) // LAWN_WIDTH
                        row = (y - LAWN_START_Y) // LAWN_HEIGHT
                        plant_x = LAWN_START_X + col * LAWN_WIDTH
                        plant_y = LAWN_START_Y + row * LAWN_HEIGHT

                        # 检查位置是否已被占用
                        can_plant = True
                        new_plant_rect = pygame.Rect(
                            plant_x, plant_y, LAWN_WIDTH, LAWN_HEIGHT)

                        for plant in self.plants:
                            if plant.get_rect().colliderect(new_plant_rect):
                                can_plant = False
                                break

                        if can_plant and self.sun >= cost:
                            self.plants.append(
                                Plant(plant_x, plant_y, plant_type))
                            self.sun -= cost
                            self.selected_plant = None

                # 检查是否点击了阳光
                for sun in self.suns[:]:
                    if sun.get_rect().collidepoint(x, y):
                        self.sun += sun.value
                        self.suns.remove(sun)
                        break

    def update(self):
        if self.game_over or self.victory:
            return

        # 更新波数计时
        self.wave_timer -= 1
        if self.wave_timer <= 0:
            self.spawn_zombie_wave()
            self.wave_timer = 900 - self.wave * 50  # 波数间隔越来越短

        # 更新僵尸生成计时
        self.zombie_spawn_timer += 1
        if self.zombie_spawn_timer >= 180:  # 每3秒可能生成一个僵尸
            if random.random() < 0.3 + self.wave * 0.05:  # 概率随波数增加
                self.spawn_zombie()
            self.zombie_spawn_timer = 0

        # 更新植物
        for plant in self.plants[:]:
            plant.update(self.projectiles, self.zombies, self.suns)
            if plant.health <= 0:
                self.plants.remove(plant)

        # 更新僵尸
        for zombie in self.zombies[:]:
            zombie.update(self.plants, self.zombies, self)
            if zombie.health <= 0:
                self.zombies.remove(zombie)
                self.sun += 25  # 击败僵尸获得阳光

        # 更新子弹
        for projectile in self.projectiles[:]:
            if projectile.update(self.zombies):
                self.projectiles.remove(projectile)

        # 更新阳光
        for sun in self.suns[:]:
            if sun.update():
                self.suns.remove(sun)

        # 自动生成阳光
        if random.random() < 0.005:  # 0.5%概率每帧生成阳光
            self.suns.append(
                Sun(random.randint(LAWN_START_X, WIDTH - 100),
                    random.randint(LAWN_START_Y, LAWN_START_Y + LAWN_HEIGHT * 5))
            )

        # 检查胜利条件
        if self.wave > 10:  # 10波后胜利
            self.victory = True

    def spawn_zombie(self):
        row = random.randint(0, LAWN_ROWS - 1)
        self.zombies.append(Zombie(row))

    def spawn_zombie_wave(self):
        # 每波生成更多僵尸
        zombies_in_wave = min(5 + self.wave, 15)

        for _ in range(zombies_in_wave):
            self.spawn_zombie()

        self.wave += 1

    def draw_game_over(self, screen):
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 200))
        screen.blit(overlay, (0, 0))

        if self.game_over:
            text = self.big_font.render("游戏结束!", True, RED)
            message = self.font.render("僵尸进入了你的房子!", True, WHITE)
        else:
            text = self.big_font.render("恭喜胜利!", True, GREEN)
            message = self.font.render(f"你成功抵御了{self.wave-1}波僵尸!", True, WHITE)

        restart_text = self.font.render("按 R 键重新开始游戏", True, YELLOW)

        screen.blit(text, (WIDTH//2 - text.get_width()//2, HEIGHT//2 - 100))
        screen.blit(message, (WIDTH//2 - message.get_width()//2, HEIGHT//2))
        screen.blit(restart_text, (WIDTH//2 -
                    restart_text.get_width()//2, HEIGHT//2 + 100))

    def run(self):
        print("=" * 50)
        print("植物大战僵尸 - 简化版")
        print("=" * 50)
        print("游戏目标: 在僵尸到达房子前消灭它们!")
        print("操作方法:")
        print("  1. 点击植物卡片选择植物")
        print("  2. 点击草坪格子种植植物")
        print("  3. 点击收集阳光")
        print("  4. 按 R 键重新开始")
        print("  5. 按 ESC 取消选择植物")
        print("植物说明:")
        print("  向日葵: 产生阳光(50阳光)")
        print("  豌豆射手: 发射豌豆(100阳光)")
        print("  坚果墙: 高生命值防御(50阳光)")
        print("  寒冰射手: 发射减速豌豆(175阳光)")
        print("=" * 50)

        while True:
            self.handle_events()
            self.update()

            # 绘制游戏
            self.draw_lawn(screen)

            # 绘制游戏元素
            for plant in self.plants:
                plant.draw(screen)

            for zombie in self.zombies:
                zombie.draw(screen)

            for projectile in self.projectiles:
                projectile.draw(screen)

            for sun in self.suns:
                sun.draw(screen)

            # 绘制UI
            self.draw_ui(screen)

            # 绘制选中的植物预览
            if self.selected_plant:
                x, y = pygame.mouse.get_pos()
                plant_type, cost = self.selected_plant

                # 绘制半透明预览
                preview_surface = pygame.Surface(
                    (LAWN_WIDTH, LAWN_HEIGHT), pygame.SRCALPHA)
                if plant_type == PlantType.SUNFLOWER:
                    color = YELLOW
                elif plant_type == PlantType.PEA_SHOOTER:
                    color = GREEN
                elif plant_type == PlantType.WALL_NUT:
                    color = BROWN
                else:  # SNOW_PEA
                    color = (200, 200, 255)

                preview_surface.fill((*color, 128))
                screen.blit(preview_surface,
                            (x - LAWN_WIDTH//2, y - LAWN_HEIGHT//2))

                # 绘制边框
                pygame.draw.rect(screen, WHITE,
                                 (x - LAWN_WIDTH//2, y - LAWN_HEIGHT//2, LAWN_WIDTH, LAWN_HEIGHT), 2)

            # 游戏结束画面
            if self.game_over or self.victory:
                self.draw_game_over(screen)

            pygame.display.flip()
            clock.tick(FPS)


# 启动游戏
if __name__ == "__main__":
    try:
        game = Game()
        game.run()
    except Exception as e:
        print(f"游戏运行出错: {e}")
        pygame.quit()
        sys.exit(1)
