import pygame
import sys
import random

# 初始化 Pygame
pygame.init()

# 常量设置
SCREEN_WIDTH, SCREEN_HEIGHT = 900, 600
FPS = 60

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (34, 139, 34)
LIGHT_GREEN = (144, 238, 144)
YELLOW = (255, 255, 0)
BROWN = (139, 69, 19)
RED = (220, 20, 60)
DARK_RED = (139, 0, 0)
BLUE = (70, 130, 180)
GRAY = (169, 169, 169)
ORANGE = (255, 165, 0)

# 游戏区域设置
GRID_LEFT = 100
GRID_TOP = 100
GRID_ROWS = 5
GRID_COLS = 9
CELL_WIDTH = 80
CELL_HEIGHT = 100

# 卡槽设置
CARD_WIDTH, CARD_HEIGHT = 70, 90
CARD_X_START = 100
CARD_Y = 10

# 植物价格
SUNFLOWER_COST = 50
PEASHOOTER_COST = 100
WALLNUT_COST = 50

# 阳光值
STARTING_SUN = 150

# 游戏状态
MENU = 0
PLAYING = 1
GAME_OVER = 2

# 僵尸生成参数（初始值）
INITIAL_ZOMBIE_SPAWN_INTERVAL = 5000  # 毫秒
ZOMBIE_SPEED = 1

# 植物生命值
SUNFLOWER_HP = 100
PEASHOOTER_HP = 100
WALLNUT_HP = 400

# 豌豆参数
PEA_SPEED = 5
PEA_DAMAGE = 25

class Sun(pygame.sprite.Sprite):
    def __init__(self, x, y, target_y=None):
        super().__init__()
        self.image = pygame.Surface((30, 30), pygame.SRCALPHA)
        pygame.draw.circle(self.image, YELLOW, (15, 15), 15)
        self.rect = self.image.get_rect(center=(x, y))
        self.target_y = target_y if target_y is not None else y
        self.falling = True if target_y else False
        self.speed = 2
        self.collectible = False
        self.lifetime = 8000
        self.spawn_time = pygame.time.get_ticks()
    
    def update(self):
        now = pygame.time.get_ticks()
        if self.falling and self.rect.centery < self.target_y:
            self.rect.y += self.speed
            if self.rect.centery >= self.target_y:
                self.falling = False
                self.collectible = True
        elif not self.falling:
            self.collectible = True
        
        if now - self.spawn_time > self.lifetime:
            self.kill()

class Plant(pygame.sprite.Sprite):
    def __init__(self, x, y, plant_type):
        super().__init__()
        self.plant_type = plant_type
        self.hp = 100
        self.cost = 0
        self.cooldown = 0
        self.last_action = 0
        
        self.image = pygame.Surface((CELL_WIDTH-10, CELL_HEIGHT-10), pygame.SRCALPHA)
        self.rect = self.image.get_rect(center=(x, y))
        self.draw_plant()
        
        if plant_type == 'sunflower':
            self.hp = SUNFLOWER_HP
            self.cost = SUNFLOWER_COST
            self.cooldown = 10000
        elif plant_type == 'peashooter':
            self.hp = PEASHOOTER_HP
            self.cost = PEASHOOTER_COST
            self.cooldown = 2000
        elif plant_type == 'wallnut':
            self.hp = WALLNUT_HP
            self.cost = WALLNUT_COST
    
    def draw_plant(self):
        self.image.fill(LIGHT_GREEN)
        if self.plant_type == 'sunflower':
            pygame.draw.circle(self.image, YELLOW, (35, 45), 20)
            pygame.draw.circle(self.image, BROWN, (35, 45), 10)
            for angle in range(0, 360, 45):
                rad = angle * 3.14159 / 180
                petal_x = 35 + int(20 * pygame.math.Vector2(1,0).rotate(angle)[0])
                petal_y = 45 + int(20 * pygame.math.Vector2(0,1).rotate(angle)[1])
                pygame.draw.circle(self.image, YELLOW, (petal_x, petal_y), 8)
        elif self.plant_type == 'peashooter':
            pygame.draw.circle(self.image, GREEN, (35, 40), 18)
            pygame.draw.circle(self.image, DARK_RED, (35, 40), 8)
            pygame.draw.rect(self.image, GREEN, (45, 35, 20, 10))
        elif self.plant_type == 'wallnut':
            pygame.draw.ellipse(self.image, BROWN, (10, 20, 50, 60))
            pygame.draw.ellipse(self.image, (101, 67, 33), (15, 25, 40, 50), 3)
            pygame.draw.circle(self.image, BLACK, (30, 45), 4)
            pygame.draw.circle(self.image, BLACK, (45, 45), 4)
    
    def take_damage(self, damage):
        self.hp -= damage
        if self.hp <= 0:
            self.kill()
    
    def update(self, now, sun_group, pea_group):
        if self.plant_type == 'sunflower':
            if now - self.last_action > self.cooldown:
                sun = Sun(self.rect.centerx, self.rect.top, self.rect.bottom + 20)
                sun_group.add(sun)
                self.last_action = now
        elif self.plant_type == 'peashooter':
            if now - self.last_action > self.cooldown:
                pea = Pea(self.rect.right, self.rect.centery)
                pea_group.add(pea)
                self.last_action = now

class Pea(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((15, 15), pygame.SRCALPHA)
        pygame.draw.circle(self.image, GREEN, (7, 7), 7)
        self.rect = self.image.get_rect(center=(x, y))
        self.speed = PEA_SPEED
        self.damage = PEA_DAMAGE
    
    def update(self):
        self.rect.x += self.speed
        if self.rect.left > SCREEN_WIDTH:
            self.kill()

class Zombie(pygame.sprite.Sprite):
    def __init__(self, y):
        super().__init__()
        self.image = pygame.Surface((40, 70), pygame.SRCALPHA)
        self.draw_zombie()
        self.rect = self.image.get_rect(midleft=(SCREEN_WIDTH + 20, y))
        self.speed = ZOMBIE_SPEED
        self.hp = 200
        self.attack_cooldown = 1000
        self.last_attack = 0
        self.target_plant = None
    
    def draw_zombie(self):
        self.image.fill(GRAY)
        pygame.draw.rect(self.image, (50, 50, 50), (5, 20, 30, 40))
        pygame.draw.circle(self.image, (70, 130, 180), (20, 15), 12)
        pygame.draw.circle(self.image, WHITE, (16, 12), 4)
        pygame.draw.circle(self.image, WHITE, (24, 12), 4)
        pygame.draw.circle(self.image, BLACK, (16, 12), 2)
        pygame.draw.circle(self.image, BLACK, (24, 12), 2)
        pygame.draw.line(self.image, (50, 50, 50), (5, 30), (0, 20), 4)
        pygame.draw.line(self.image, (50, 50, 50), (35, 30), (40, 20), 4)
    
    def update(self, now, plant_group, pea_group, game_state):
        self.target_plant = None
        for plant in plant_group:
            if plant.rect.colliderect(self.rect.inflate(-20, -10)) and self.rect.left > plant.rect.left:
                self.target_plant = plant
                break
        
        if self.target_plant:
            if now - self.last_attack > self.attack_cooldown:
                self.target_plant.take_damage(20)
                self.last_attack = now
        else:
            self.rect.x -= self.speed
        
        if self.rect.right <= GRID_LEFT - 20:
            game_state['state'] = GAME_OVER
        
        hit_peas = pygame.sprite.spritecollide(self, pea_group, True)
        for pea in hit_peas:
            self.hp -= pea.damage
        if self.hp <= 0:
            self.kill()

class Game:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("植物大战僵尸 - Pygame版")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None, 36)
        self.big_font = pygame.font.Font(None, 72)
        
        self.state = MENU
        self.sun_points = STARTING_SUN
        self.selected_plant = None
        self.game_result = ""
        
        self.sun_group = pygame.sprite.Group()
        self.plant_group = pygame.sprite.Group()
        self.zombie_group = pygame.sprite.Group()
        self.pea_group = pygame.sprite.Group()
        
        self.last_zombie_spawn = 0
        self.zombie_spawn_interval = INITIAL_ZOMBIE_SPAWN_INTERVAL  # 实例变量
        self.last_sun_drop = 0
        self.sun_drop_interval = 7000
        
        self.game_state = {'state': PLAYING}
        
        self.cards = [
            {'type': 'sunflower', 'cost': SUNFLOWER_COST, 'rect': pygame.Rect(CARD_X_START, CARD_Y, CARD_WIDTH, CARD_HEIGHT)},
            {'type': 'peashooter', 'cost': PEASHOOTER_COST, 'rect': pygame.Rect(CARD_X_START + CARD_WIDTH + 10, CARD_Y, CARD_WIDTH, CARD_HEIGHT)},
            {'type': 'wallnut', 'cost': WALLNUT_COST, 'rect': pygame.Rect(CARD_X_START + 2*(CARD_WIDTH+10), CARD_Y, CARD_WIDTH, CARD_HEIGHT)},
        ]
    
    def draw_grid(self):
        for row in range(GRID_ROWS):
            for col in range(GRID_COLS):
                x = GRID_LEFT + col * CELL_WIDTH
                y = GRID_TOP + row * CELL_HEIGHT
                rect = pygame.Rect(x, y, CELL_WIDTH, CELL_HEIGHT)
                color = LIGHT_GREEN if (row + col) % 2 == 0 else GREEN
                pygame.draw.rect(self.screen, color, rect)
                pygame.draw.rect(self.screen, BLACK, rect, 1)
    
    def draw_ui(self):
        sun_text = self.font.render(f"☀ {self.sun_points}", True, YELLOW)
        self.screen.blit(sun_text, (10, 10))
        
        pygame.draw.rect(self.screen, GRAY, (CARD_X_START - 10, CARD_Y - 10, 3*CARD_WIDTH+40, CARD_HEIGHT+20))
        
        for card in self.cards:
            color = GREEN if self.selected_plant == card['type'] else WHITE
            if self.sun_points < card['cost']:
                color = RED
            pygame.draw.rect(self.screen, color, card['rect'])
            name = card['type'][:4]
            text = self.font.render(name, True, BLACK)
            cost_text = self.font.render(str(card['cost']), True, BLACK)
            self.screen.blit(text, (card['rect'].x+5, card['rect'].y+10))
            self.screen.blit(cost_text, (card['rect'].x+5, card['rect'].y+40))
        
        shovel_text = self.font.render("右键取消选择", True, WHITE)
        self.screen.blit(shovel_text, (CARD_X_START + 3*(CARD_WIDTH+10) + 20, CARD_Y + 20))
    
    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            
            if self.state == MENU:
                if event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
                    self.state = PLAYING
                    self.game_state['state'] = PLAYING
            
            elif self.state == PLAYING:
                if event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_pos = pygame.mouse.get_pos()
                    if event.button == 3:
                        self.selected_plant = None
                        continue
                    
                    if event.button == 1:
                        card_clicked = False
                        for card in self.cards:
                            if card['rect'].collidepoint(mouse_pos):
                                if self.sun_points >= card['cost']:
                                    self.selected_plant = card['type']
                                card_clicked = True
                                break
                        
                        if not card_clicked and self.selected_plant:
                            grid_x = (mouse_pos[0] - GRID_LEFT) // CELL_WIDTH
                            grid_y = (mouse_pos[1] - GRID_TOP) // CELL_HEIGHT
                            if 0 <= grid_x < GRID_COLS and 0 <= grid_y < GRID_ROWS:
                                center_x = GRID_LEFT + grid_x * CELL_WIDTH + CELL_WIDTH//2
                                center_y = GRID_TOP + grid_y * CELL_HEIGHT + CELL_HEIGHT//2
                                occupied = any(plant.rect.collidepoint(center_x, center_y) for plant in self.plant_group)
                                if not occupied:
                                    cost = next(c['cost'] for c in self.cards if c['type'] == self.selected_plant)
                                    if self.sun_points >= cost:
                                        new_plant = Plant(center_x, center_y, self.selected_plant)
                                        self.plant_group.add(new_plant)
                                        self.sun_points -= cost
                                        self.selected_plant = None
                        
                        # 收集阳光
                        for sun in self.sun_group:
                            if sun.rect.collidepoint(mouse_pos) and sun.collectible:
                                self.sun_points += 25
                                sun.kill()
            
            elif self.state == GAME_OVER:
                if event.type == pygame.KEYDOWN:
                    self.__init__()
    
    def update(self):
        if self.state != PLAYING:
            return
        
        now = pygame.time.get_ticks()
        
        # 使用实例变量 zombie_spawn_interval
        if now - self.last_zombie_spawn > self.zombie_spawn_interval:
            row = random.randint(0, GRID_ROWS-1)
            y_pos = GRID_TOP + row * CELL_HEIGHT + CELL_HEIGHT//2
            self.zombie_group.add(Zombie(y_pos))
            self.last_zombie_spawn = now
            # 逐渐缩短生成间隔（难度增加）
            self.zombie_spawn_interval = max(2000, self.zombie_spawn_interval - 100)
        
        if now - self.last_sun_drop > self.sun_drop_interval:
            drop_x = random.randint(GRID_LEFT, GRID_LEFT + GRID_COLS * CELL_WIDTH)
            sun = Sun(drop_x, 0, random.randint(GRID_TOP, GRID_TOP + GRID_ROWS * CELL_HEIGHT))
            self.sun_group.add(sun)
            self.last_sun_drop = now
        
        self.sun_group.update()
        self.plant_group.update(now, self.sun_group, self.pea_group)
        self.zombie_group.update(now, self.plant_group, self.pea_group, self.game_state)
        self.pea_group.update()
        
        # 清除出界的豌豆
        for pea in list(self.pea_group):
            if pea.rect.left > SCREEN_WIDTH:
                pea.kill()
        
        if self.game_state['state'] == GAME_OVER:
            self.state = GAME_OVER
    
    def draw(self):
        self.screen.fill(BLACK)
        
        if self.state == MENU:
            title = self.big_font.render("植物大战僵尸", True, YELLOW)
            prompt = self.font.render("点击任意位置开始", True, WHITE)
            self.screen.blit(title, (SCREEN_WIDTH//2 - title.get_width()//2, SCREEN_HEIGHT//2 - 50))
            self.screen.blit(prompt, (SCREEN_WIDTH//2 - prompt.get_width()//2, SCREEN_HEIGHT//2 + 50))
        
        elif self.state == PLAYING:
            self.draw_grid()
            self.draw_ui()
            self.sun_group.draw(self.screen)
            self.plant_group.draw(self.screen)
            self.pea_group.draw(self.screen)
            self.zombie_group.draw(self.screen)
            
            if self.selected_plant:
                mouse_x, mouse_y = pygame.mouse.get_pos()
                preview = pygame.Surface((CELL_WIDTH-10, CELL_HEIGHT-10), pygame.SRCALPHA)
                preview.fill((*LIGHT_GREEN, 128))
                self.screen.blit(preview, (mouse_x - (CELL_WIDTH-10)//2, mouse_y - (CELL_HEIGHT-10)//2))
        
        elif self.state == GAME_OVER:
            over_text = self.big_font.render("游戏结束", True, RED)
            restart_text = self.font.render("按任意键重新开始", True, WHITE)
            self.screen.blit(over_text, (SCREEN_WIDTH//2 - over_text.get_width()//2, SCREEN_HEIGHT//2 - 50))
            self.screen.blit(restart_text, (SCREEN_WIDTH//2 - restart_text.get_width()//2, SCREEN_HEIGHT//2 + 50))
        
        pygame.display.flip()
    
    def run(self):
        while True:
            self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(FPS)

if __name__ == "__main__":
    game = Game()
    game.run()