植物大战僵尸 plus

有学号

点击查看代码
import pygame
import random
import sys
import os
import math
from pygame.locals import *

# 初始化pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 600
FPS = 60
GRID_SIZE = 80
GRID_WIDTH = 9
GRID_HEIGHT = 5
LAWN_LEFT = 150
LAWN_TOP = 100

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
BROWN = (139, 69, 19)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GRAY = (100, 100, 100)
PURPLE = (128, 0, 128)

# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("植物大战僵尸 - 优化版")
clock = pygame.time.Clock()

# 创建更复杂的图像
def create_complex_sun():
    surf = pygame.Surface((40, 40), pygame.SRCALPHA)
    pygame.draw.circle(surf, YELLOW, (20, 20), 20)
    for i in range(8):
        angle = i * 45
        end_x = 20 + 25 * pygame.math.Vector2(1, 0).rotate(angle).x
        end_y = 20 + 25 * pygame.math.Vector2(1, 0).rotate(angle).y
        pygame.draw.line(surf, YELLOW, (20, 20), (end_x, end_y), 3)
    pygame.draw.circle(surf, (255, 165, 0), (20, 20), 15)
    return surf

def create_complex_sunflower():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 茎
    pygame.draw.rect(surf, GREEN, (28, 30, 4, 30))
    # 花盆
    pygame.draw.rect(surf, BROWN, (20, 50, 20, 10))
    # 花心
    pygame.draw.circle(surf, (139, 69, 19), (30, 25), 15)
    # 花瓣
    for i in range(8):
        angle = i * 45
        end_x = 30 + 25 * pygame.math.Vector2(1, 0).rotate(angle).x
        end_y = 25 + 25 * pygame.math.Vector2(1, 0).rotate(angle).y
        pygame.draw.circle(surf, (255, 215, 0), (end_x, end_y), 10)
    # 笑脸
    pygame.draw.circle(surf, BLACK, (25, 20), 2)
    pygame.draw.circle(surf, BLACK, (35, 20), 2)
    pygame.draw.arc(surf, BLACK, (22, 25, 16, 10), 0.2, 2.9, 2)
    return surf

def create_complex_zombie():
    surf = pygame.Surface((50, 80), pygame.SRCALPHA)
    # 身体
    pygame.draw.ellipse(surf, (150, 150, 150), (10, 20, 30, 50))
    # 头
    pygame.draw.circle(surf, (200, 200, 200), (25, 20), 15)
    # 眼睛
    pygame.draw.circle(surf, (50, 50, 50), (20, 18), 3)
    pygame.draw.circle(surf, (50, 50, 50), (30, 18), 3)
    # 嘴巴
    pygame.draw.rect(surf, (100, 0, 0), (20, 25, 10, 3))
    # 衣服
    pygame.draw.rect(surf, (70, 70, 70), (10, 35, 30, 15))
    pygame.draw.line(surf, (100, 100, 100), (10, 42), (40, 42), 2)
    # 手臂
    pygame.draw.line(surf, (200, 200, 200), (10, 40), (0, 50), 5)
    pygame.draw.line(surf, (200, 200, 200), (40, 40), (50, 50), 5)
    # 腿
    pygame.draw.line(surf, (70, 70, 70), (20, 70), (20, 80), 5)
    pygame.draw.line(surf, (70, 70, 70), (30, 70), (30, 80), 5)
    # 僵尸标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("Z", True, RED)
    surf.blit(text, (40, 10))
    return surf

def create_complex_peashooter():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 茎
    pygame.draw.rect(surf, GREEN, (28, 30, 4, 30))
    # 花盆
    pygame.draw.rect(surf, BROWN, (20, 50, 20, 10))
    # 头部
    pygame.draw.circle(surf, GREEN, (30, 25), 15)
    # 嘴巴
    pygame.draw.circle(surf, (0, 100, 0), (35, 25), 8)
    # 眼睛
    pygame.draw.circle(surf, BLACK, (25, 20), 3)
    # 豌豆标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("P", True, (0, 100, 0))
    surf.blit(text, (20, 15))
    return surf

def create_complex_wallnut():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 坚果
    pygame.draw.ellipse(surf, BROWN, (10, 10, 40, 50))
    # 纹理
    pygame.draw.line(surf, (101, 67, 33), (20, 20), (40, 25), 2)
    pygame.draw.line(surf, (101, 67, 33), (25, 30), (35, 40), 2)
    pygame.draw.line(surf, (101, 67, 33), (30, 45), (20, 50), 2)
    # 表情
    pygame.draw.circle(surf, BLACK, (25, 30), 2)
    pygame.draw.circle(surf, BLACK, (35, 30), 2)
    pygame.draw.arc(surf, BLACK, (22, 35, 16, 10), 0.2, 2.9, 2)
    # 坚果标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("W", True, (101, 67, 33))
    surf.blit(text, (40, 20))
    return surf

def create_complex_pea():
    surf = pygame.Surface((20, 10), pygame.SRCALPHA)
    pygame.draw.ellipse(surf, (50, 200, 50), (0, 0, 20, 10))
    pygame.draw.ellipse(surf, (0, 100, 0), (5, 2, 10, 6))
    return surf

def create_complex_shovel():
    surf = pygame.Surface((40, 40), pygame.SRCALPHA)
    # 手柄
    pygame.draw.rect(surf, BROWN, (15, 5, 10, 20))
    # 铲头
    points = [(10, 25), (30, 25), (25, 40), (15, 40)]
    pygame.draw.polygon(surf, (180, 180, 180), points)
    return surf

def create_complex_pepper():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 茎
    pygame.draw.rect(surf, GREEN, (28, 30, 4, 30))
    # 花盆
    pygame.draw.rect(surf, BROWN, (20, 50, 20, 10))
    # 辣椒
    pygame.draw.ellipse(surf, RED, (15, 15, 30, 40))
    # 火焰效果
    for i in range(5):
        angle = random.randint(0, 360)
        length = random.randint(5, 15)
        end_x = 30 + length * math.cos(math.radians(angle))
        end_y = 30 + length * math.sin(math.radians(angle))
        pygame.draw.line(surf, (255, 165, 0), (30, 30), (end_x, end_y), 3)
    # 标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("F", True, WHITE)
    surf.blit(text, (45, 20))
    return surf

def create_lawnmower():
    surf = pygame.Surface((60, 40), pygame.SRCALPHA)
    # 车身
    pygame.draw.rect(surf, (50, 200, 50), (0, 10, 50, 20))
    # 轮子
    pygame.draw.circle(surf, BLACK, (10, 30), 8)
    pygame.draw.circle(surf, BLACK, (40, 30), 8)
    # 刀片
    pygame.draw.rect(surf, (200, 200, 200), (50, 15, 10, 10))
    return surf

# 创建更复杂的图像资源
sun_img = create_complex_sun()
sunflower_img = create_complex_sunflower()
peashooter_img = create_complex_peashooter()
wallnut_img = create_complex_wallnut()
zombie_img = create_complex_zombie()
pea_img = create_complex_pea()
shovel_img = create_complex_shovel()
pepper_img = create_complex_pepper()
lawnmower_img = create_lawnmower()

# 游戏字体
font = pygame.font.SysFont('Arial', 24)
big_font = pygame.font.SysFont('Arial', 36, bold=True)
title_font = pygame.font.SysFont('Arial', 48, bold=True)

class Sun:
    def __init__(self, x, y, is_falling=True):
        self.x = x
        self.y = y
        self.image = sun_img
        self.rect = self.image.get_rect(center=(x, y))
        self.value = 25
        self.speed = 2
        self.is_falling = is_falling
        self.collected = False
        self.fall_target_y = y + random.randint(100, 200)
        self.lifetime = 0
        self.max_lifetime = 10 * FPS  # 10秒
    
    def update(self):
        self.lifetime += 1
        if self.lifetime >= self.max_lifetime:
            self.collected = True
        
        if self.is_falling and self.y < self.fall_target_y:
            self.y += self.speed
            self.rect.center = (self.x, self.y)
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)
    
    def is_clicked(self, pos):
        return self.rect.collidepoint(pos) and not self.collected

class Plant:
    def __init__(self, x, y, plant_type):
        self.x = x
        self.y = y
        self.plant_type = plant_type
        self.health = 100
        self.attack_cooldown = 0
        self.eaten = False  # 是否正在被吃
        
        if plant_type == "peashooter":
            self.image = peashooter_img
            self.cost = 100
            self.attack_speed = 2 * FPS  # 每2秒攻击一次
        elif plant_type == "sunflower":
            self.image = sunflower_img
            self.cost = 50
            self.sun_production_speed = 10 * FPS  # 每10秒产生阳光
            self.sun_production_timer = 0
        elif plant_type == "wallnut":
            self.image = wallnut_img
            self.cost = 50
            self.health = 300  # 坚果墙有更多生命值
        elif plant_type == "pepper":
            self.image = pepper_img
            self.cost = 150
            self.exploded = False
        
        self.rect = self.image.get_rect(center=(x, y))
    
    def update(self):
        if self.plant_type == "peashooter":
            if self.attack_cooldown > 0:
                self.attack_cooldown -= 1
        elif self.plant_type == "sunflower":
            self.sun_production_timer += 1
            if self.sun_production_timer >= self.sun_production_speed:
                self.sun_production_timer = 0
                return True  # 表示应该产生阳光
        elif self.plant_type == "pepper":
            # 辣椒种植后立即爆炸
            if not self.exploded:
                self.exploded = True
                return "explode"
        return False
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)
        # 绘制生命条(辣椒不需要)
        if self.plant_type != "pepper":
            health_bar_width = 40
            health_ratio = self.health / (300 if self.plant_type == "wallnut" else 100)
            pygame.draw.rect(surface, RED, (self.x - health_bar_width//2, self.y - 40, health_bar_width, 5))
            pygame.draw.rect(surface, GREEN, (self.x - health_bar_width//2, self.y - 40, int(health_bar_width * health_ratio), 5))
        student_id_text = font.render("学号:03", True, BLACK)
        surface.blit(student_id_text, (10, 10))
    def can_attack(self):
        return self.plant_type == "peashooter" and self.attack_cooldown <= 0
    
    def attack(self):
        if self.plant_type == "peashooter":
            self.attack_cooldown = self.attack_speed
            return Pea(self.x + 30, self.y)
        return None

class Pea:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.image = pea_img
        self.rect = self.image.get_rect(center=(x, y))
        self.speed = 5
        self.damage = 20
    
    def update(self):
        self.x += self.speed
        self.rect.center = (self.x, self.y)
        return self.x > SCREEN_WIDTH  # 如果豌豆飞出屏幕则返回True
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)

class Zombie:
    def __init__(self, row, level):
        self.x = SCREEN_WIDTH
        self.y = LAWN_TOP + row * GRID_SIZE + GRID_SIZE // 2
        self.image = zombie_img
        self.rect = self.image.get_rect(midright=(self.x, self.y))
        # 僵尸速度随关卡增加而增加(初始速度降低)
        self.speed = 0.15 + level * 0.05
        self.health = 100 + level * 20  # 僵尸生命值随关卡增加
        self.damage = 0.5 + level * 0.1  # 僵尸伤害随关卡增加
        self.attack_cooldown = 0
        self.row = row
        self.walk_animation = 0
        self.walk_speed = 0.1
        self.eating = False  # 是否正在吃植物
        self.eat_timer = 0  # 吃植物计时器
        self.current_plant = None  # 当前正在吃的植物
    
    def update(self):
        # 如果正在吃植物,则停止移动
        if not self.eating:
            self.walk_animation += self.walk_speed
            if self.walk_animation >= 2:
                self.walk_animation = 0
            
            # 轻微左右摆动模拟走路
            swing_offset = 2 * math.sin(self.walk_animation * math.pi)
            self.x -= self.speed
            self.rect.midright = (self.x, self.y + swing_offset)
        
        # 吃植物计时
        if self.eating:
            self.eat_timer += 1
            
            # 坚果需要更长时间吃完
            eat_time = 3 * FPS if self.current_plant and self.current_plant.plant_type == "wallnut" else 1 * FPS
            
            if self.eat_timer >= eat_time:
                self.eating = False
                self.eat_timer = 0
                self.current_plant = None
        
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
    
    def start_eating(self, plant):
        """开始吃植物"""
        self.eating = True
        self.eat_timer = 0
        self.current_plant = plant
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)
        # 绘制生命条
        health_bar_width = 40
        health_ratio = self.health / (100 + self.health * 0.2)
        pygame.draw.rect(surface, RED, (self.x - health_bar_width//2, self.y - 50, health_bar_width, 5))
        pygame.draw.rect(surface, GREEN, (self.x - health_bar_width//2, self.y - 50, int(health_bar_width * health_ratio), 5))
        
        # 如果正在吃植物,绘制吃植物状态
        if self.eating:
            eat_text = font.render("吃...", True, RED)
            surface.blit(eat_text, (self.x - 20, self.y - 70))
    
    def can_attack(self):
        return self.attack_cooldown <= 0
    
    def attack(self, plant):
        self.attack_cooldown = FPS  # 1秒攻击一次
        plant.health -= self.damage
        return plant.health <= 0  # 返回植物是否被摧毁

class Lawnmower:
    def __init__(self, row):
        self.row = row
        self.x = LAWN_LEFT - 30
        self.y = LAWN_TOP + row * GRID_SIZE + GRID_SIZE // 2
        self.image = lawnmower_img
        self.rect = self.image.get_rect(center=(self.x, self.y))
        self.active = False
        self.speed = 10
        self.used = False  # 是否已使用
    
    def activate(self):
        if not self.used:
            self.active = True
            self.used = True
    
    def update(self):
        if self.active:
            self.x += self.speed
            self.rect.center = (self.x, self.y)
            return self.x > SCREEN_WIDTH  # 如果小推车移出屏幕则返回True
        return False
    
    def draw(self, surface):
        if not self.active:
            surface.blit(self.image, self.rect)

class Game:
    def __init__(self):
        self.plants = []
        self.zombies = []
        self.suns = []
        self.peas = []
        self.sun_count = 150
        self.selected_plant = None
        self.game_over = False
        self.wave_timer = 0
        self.zombie_spawn_timer = 0
        self.sun_spawn_timer = 0
        self.sun_spawn_interval = 10 * FPS  # 10秒自动生成一个阳光
        self.score = 0
        self.level = 1
        self.max_level = 5
        self.unlocked_level = 1
        self.state = "menu"  # menu, level_select, playing, game_over
        self.shovel_selected = False
        self.lawnmowers = [Lawnmower(i) for i in range(GRID_HEIGHT)]
        self.zombies_killed_this_wave = 0
        self.zombies_to_spawn = 0
        self.wave_completed = False
        
        # 初始化关卡数据(减少第一关僵尸数量)
        self.level_data = [
            {"waves": 1, "zombies_per_wave": 3, "description": "新手训练营"},  # 第一关只有3个僵尸
            {"waves": 2, "zombies_per_wave": 8, "description": "僵尸入侵开始"},
            {"waves": 2, "zombies_per_wave": 12, "description": "僵尸大军来袭"},
            {"waves": 3, "zombies_per_wave": 15, "description": "僵尸狂潮"},
            {"waves": 3, "zombies_per_wave": 20, "description": "最终决战"}
        ]
        
        # 植物卡片
        self.plant_cards = [
            {"type": "sunflower", "cost": 50, "rect": pygame.Rect(10, 10, 60, 80)},
            {"type": "peashooter", "cost": 100, "rect": pygame.Rect(10, 100, 60, 80)},
        ]
        
        # 铲子卡片
        self.shovel_card = {"type": "shovel", "cost": 0, "rect": pygame.Rect(10, 280, 60, 80)}
    
    def start_level(self, level):
        self.level = level
        self.plants = []
        self.zombies = []
        self.suns = []
        self.peas = []
        self.sun_count = 150
        self.selected_plant = None
        self.game_over = False
        self.wave_timer = 0
        self.zombie_spawn_timer = 0
        self.sun_spawn_timer = 0
        self.score = 0
        self.shovel_selected = False
        self.lawnmowers = [Lawnmower(i) for i in range(GRID_HEIGHT)]
        self.zombies_killed_this_wave = 0
        self.current_wave = 1
        self.zombies_to_spawn = self.level_data[level-1]["zombies_per_wave"]
        self.wave_completed = False
        
        # 根据关卡解锁植物
        self.plant_cards = [
            {"type": "sunflower", "cost": 50, "rect": pygame.Rect(10, 10, 60, 80)},
            {"type": "peashooter", "cost": 100, "rect": pygame.Rect(10, 100, 60, 80)},
        ]
        
        if level >= 2:  # 第二关解锁坚果
            self.plant_cards.append({"type": "wallnut", "cost": 50, "rect": pygame.Rect(10, 190, 60, 80)})
        
        if level >= 4:  # 第四关解锁辣椒
            self.plant_cards.append({"type": "pepper", "cost": 150, "rect": pygame.Rect(10, 280, 60, 80)})
        
        self.state = "playing"
    
    def spawn_sun(self, x=None, y=None, is_falling=True):
        if x is None:
            x = random.randint(LAWN_LEFT, LAWN_LEFT + GRID_WIDTH * GRID_SIZE)
        if y is None and is_falling:
            y = 0
        self.suns.append(Sun(x, y, is_falling))
    
    def spawn_zombie(self):
        row = random.randint(0, GRID_HEIGHT - 1)
        self.zombies.append(Zombie(row, self.level))
        self.zombies_to_spawn -= 1
    
    def update(self):
        if self.game_over or self.state != "playing":
            return
        
        # 更新阳光
        for sun in self.suns[:]:
            sun.update()
            if sun.collected:
                self.suns.remove(sun)
        
        # 更新植物
        for plant in self.plants[:]:
            result = plant.update()
            if result == True:  # 向日葵产生阳光
                self.spawn_sun(plant.x, plant.y + 30, False)
            elif result == "explode":  # 辣椒爆炸
                # 消灭附近僵尸
                for zombie in self.zombies[:]:
                    if abs(zombie.y - plant.y) < 100 and abs(zombie.x - plant.x) < 200:
                        self.zombies.remove(zombie)
                        self.score += 10
                        self.zombies_killed_this_wave += 1
                # 移除辣椒
                self.plants.remove(plant)
            
            # 检查植物是否需要攻击
            if plant.can_attack():
                # 检查该行是否有僵尸
                plant_row = (plant.y - LAWN_TOP) // GRID_SIZE
                zombies_in_row = [z for z in self.zombies if z.row == plant_row and z.x > plant.x]
                
                if zombies_in_row:
                    pea = plant.attack()
                    if pea:
                        self.peas.append(pea)
        
        # 更新豌豆
        for pea in self.peas[:]:
            if pea.update():  # 如果豌豆飞出屏幕
                self.peas.remove(pea)
                continue
            
            # 检查豌豆是否击中僵尸
            for zombie in self.zombies[:]:
                if pea.rect.colliderect(zombie.rect):
                    zombie.health -= pea.damage
                    if zombie.health <= 0:
                        self.zombies.remove(zombie)
                        self.score += 10
                        self.zombies_killed_this_wave += 1
                    self.peas.remove(pea)
                    break
        
        # 更新僵尸
        for zombie in self.zombies[:]:
            # 如果僵尸没有在吃植物,检查是否碰到植物
            if not zombie.eating:
                plant_collision = None
                for plant in self.plants:
                    if zombie.rect.colliderect(plant.rect):
                        plant_collision = plant
                        break
                
                if plant_collision:
                    # 开始吃植物
                    zombie.start_eating(plant_collision)
            
            zombie.update()
            
            # 如果僵尸在吃植物,进行攻击
            if zombie.eating and zombie.current_plant:
                if zombie.can_attack():
                    plant_destroyed = zombie.attack(zombie.current_plant)
                    if plant_destroyed:
                        self.plants.remove(zombie.current_plant)
                        zombie.eating = False
                        zombie.current_plant = None
            else:
                # 检查僵尸是否到达小推车位置
                if zombie.x < LAWN_LEFT:
                    # 激活小推车
                    self.lawnmowers[zombie.row].activate()
        
        # 更新小推车
        for lawnmower in self.lawnmowers[:]:
            if lawnmower.update():  # 如果小推车移出屏幕
                self.lawnmowers.remove(lawnmower)
            else:
                # 检查小推车是否消灭僵尸
                if lawnmower.active:
                    for zombie in self.zombies[:]:
                        if zombie.row == lawnmower.row and abs(zombie.x - lawnmower.x) < 50:
                            self.zombies.remove(zombie)
                            self.score += 10
                            self.zombies_killed_this_wave += 1
        
        # 检查小推车是否失效
        for i, lawnmower in enumerate(self.lawnmowers):
            if lawnmower.used and not lawnmower.active:
                # 检查是否有僵尸越过失效的小推车
                for zombie in self.zombies:
                    if zombie.row == i and zombie.x < LAWN_LEFT:
                        self.game_over = True
        
        # 自动生成阳光
        self.sun_spawn_timer += 1
        if self.sun_spawn_timer >= self.sun_spawn_interval:
            self.sun_spawn_timer = 0
            self.spawn_sun()
        
        # 生成僵尸
        if self.zombies_to_spawn > 0:
            self.zombie_spawn_timer += 1
            spawn_interval = max(1, 60 - self.level * 5)  # 随关卡增加生成速度
            if self.zombie_spawn_timer >= spawn_interval:
                self.zombie_spawn_timer = 0
                self.spawn_zombie()
        
        # 检查波次是否完成
        if self.zombies_to_spawn == 0 and len(self.zombies) == 0:
            if self.current_wave < self.level_data[self.level-1]["waves"]:
                self.current_wave += 1
                self.zombies_to_spawn = self.level_data[self.level-1]["zombies_per_wave"]
                self.zombies_killed_this_wave = 0
                self.wave_completed = True
                self.wave_timer = 0
            else:
                # 完成所有波次
                self.game_over = True
                if self.level == self.unlocked_level and self.unlocked_level < self.max_level:
                    self.unlocked_level += 1
    
    def draw(self, surface):
        # 绘制背景
        surface.fill((135, 206, 235))  # 天空蓝
        
        if self.state == "menu":
            # 绘制主菜单
            title = title_font.render("植物大战僵尸", True, GREEN)
            surface.blit(title, (SCREEN_WIDTH//2 - title.get_width()//2, 100))
            
            start_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 200, 200, 60)
            pygame.draw.rect(surface, (100, 200, 100), start_btn)
            pygame.draw.rect(surface, BLACK, start_btn, 3)
            start_text = big_font.render("开始游戏", True, WHITE)
            surface.blit(start_text, (SCREEN_WIDTH//2 - start_text.get_width()//2, 215))
            
            level_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 280, 200, 60)
            pygame.draw.rect(surface, (100, 150, 200), level_btn)
            pygame.draw.rect(surface, BLACK, level_btn, 3)
            level_text = big_font.render("选择关卡", True, WHITE)
            surface.blit(level_text, (SCREEN_WIDTH//2 - level_text.get_width()//2, 295))
            
            quit_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 360, 200, 60)
            pygame.draw.rect(surface, (200, 100, 100), quit_btn)
            pygame.draw.rect(surface, BLACK, quit_btn, 3)
            quit_text = big_font.render("退出游戏", True, WHITE)
            surface.blit(quit_text, (SCREEN_WIDTH//2 - quit_text.get_width()//2, 375))
            
            # 绘制最高解锁关卡
            level_text = font.render(f"已解锁关卡: {self.unlocked_level}/{self.max_level}", True, BLACK)
            surface.blit(level_text, (SCREEN_WIDTH//2 - level_text.get_width()//2, 450))
            
        elif self.state == "level_select":
            # 绘制关卡选择界面
            title = title_font.render("选择关卡", True, GREEN)
            surface.blit(title, (SCREEN_WIDTH//2 - title.get_width()//2, 50))
            
            for i in range(self.max_level):
                unlocked = i < self.unlocked_level
                level_btn = pygame.Rect(150 + (i % 3) * 200, 150 + (i // 3) * 120, 150, 80)
                
                if unlocked:
                    pygame.draw.rect(surface, (100, 200, 100), level_btn)
                else:
                    pygame.draw.rect(surface, (150, 150, 150), level_btn)
                
                pygame.draw.rect(surface, BLACK, level_btn, 3)
                
                level_text = big_font.render(f"关卡 {i+1}", True, WHITE if unlocked else BLACK)
                surface.blit(level_text, (level_btn.x + 75 - level_text.get_width()//2, level_btn.y + 25))
                
                desc_text = font.render(self.level_data[i]["description"], True, BLACK)
                surface.blit(desc_text, (level_btn.x + 75 - desc_text.get_width()//2, level_btn.y + 55))
            
            back_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 450, 200, 60)
            pygame.draw.rect(surface, (200, 150, 100), back_btn)
            pygame.draw.rect(surface, BLACK, back_btn, 3)
            back_text = big_font.render("返回主菜单", True, WHITE)
            surface.blit(back_text, (SCREEN_WIDTH//2 - back_text.get_width()//2, 465))
            
        elif self.state == "playing":
            # 绘制草坪网格
            for row in range(GRID_HEIGHT):
                for col in range(GRID_WIDTH):
                    rect = pygame.Rect(
                        LAWN_LEFT + col * GRID_SIZE,
                        LAWN_TOP + row * GRID_SIZE,
                        GRID_SIZE,
                        GRID_SIZE
                    )
                    pygame.draw.rect(surface, (124, 252, 0), rect)
                    pygame.draw.rect(surface, BLACK, rect, 1)
            
            # 绘制小推车
            for lawnmower in self.lawnmowers:
                lawnmower.draw(surface)
            
            # 绘制植物卡片
            for card in self.plant_cards:
                color = (200, 200, 200) if self.sun_count >= card["cost"] else (100, 100, 100)
                pygame.draw.rect(surface, color, card["rect"])
                pygame.draw.rect(surface, BLACK, card["rect"], 2)
                
                if card["type"] == "sunflower":
                    plant_img = sunflower_img
                elif card["type"] == "peashooter":
                    plant_img = peashooter_img
                elif card["type"] == "wallnut":
                    plant_img = wallnut_img
                elif card["type"] == "pepper":
                    plant_img = pepper_img
                
                surface.blit(plant_img, (card["rect"].x + 10, card["rect"].y + 10))
                
                # 绘制成本
                cost_text = font.render(str(card["cost"]), True, BLACK)
                surface.blit(cost_text, (card["rect"].x + 20, card["rect"].y + 60))
            
            # 绘制铲子卡片
            shovel_color = (200, 150, 150) if self.shovel_selected else (200, 200, 200)
            pygame.draw.rect(surface, shovel_color, self.shovel_card["rect"])
            pygame.draw.rect(surface, BLACK, self.shovel_card["rect"], 2)
            surface.blit(shovel_img, (self.shovel_card["rect"].x + 10, self.shovel_card["rect"].y + 10))
            shovel_text = font.render("铲子", True, BLACK)
            surface.blit(shovel_text, (self.shovel_card["rect"].x + 10, self.shovel_card["rect"].y + 60))
            
            # 绘制选中的植物(跟随鼠标)
            if self.selected_plant:
                mouse_x, mouse_y = pygame.mouse.get_pos()
                if self.selected_plant == "sunflower":
                    plant_img = sunflower_img
                elif self.selected_plant == "peashooter":
                    plant_img = peashooter_img
                elif self.selected_plant == "wallnut":
                    plant_img = wallnut_img
                elif self.selected_plant == "pepper":
                    plant_img = pepper_img
                
                surface.blit(plant_img, (mouse_x - 30, mouse_y - 30))
            
            # 绘制植物
            for plant in self.plants:
                plant.draw(surface)
            
            # 绘制僵尸
            for zombie in self.zombies:
                zombie.draw(surface)
            
            # 绘制豌豆
            for pea in self.peas:
                pea.draw(surface)
            
            # 绘制阳光
            for sun in self.suns:
                sun.draw(surface)
            
            # 绘制游戏信息
            pygame.draw.rect(surface, (200, 200, 200, 180), (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 10, 10, 180, 120))
            pygame.draw.rect(surface, BLACK, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 10, 10, 180, 120), 2)
            
            # 绘制阳光计数
            sun_text = font.render(f"阳光: {self.sun_count}", True, BLACK)
            surface.blit(sun_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 20))
            
            # 绘制分数
            score_text = font.render(f"分数: {self.score}", True, BLACK)
            surface.blit(score_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 50))
            
            # 绘制关卡和波次信息
            level_text = font.render(f"关卡: {self.level}", True, BLACK)
            surface.blit(level_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 80))
            
            wave_text = font.render(f"波次: {self.current_wave}/{self.level_data[self.level-1]['waves']}", True, BLACK)
            surface.blit(wave_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 110))
            
            # 绘制返回按钮
            back_btn = pygame.Rect(LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 140, 140, 30)
            pygame.draw.rect(surface, (200, 100, 100), back_btn)
            pygame.draw.rect(surface, BLACK, back_btn, 2)
            back_text = font.render("返回主菜单", True, WHITE)
            surface.blit(back_text, (back_btn.x + 10, back_btn.y + 5))
            
            # 波次完成提示
            if self.wave_completed:
                self.wave_timer += 1
                if self.wave_timer < 3 * FPS:  # 显示3秒
                    wave_surf = pygame.Surface((300, 60), pygame.SRCALPHA)
                    wave_surf.fill((0, 0, 0, 150))
                    surface.blit(wave_surf, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT//2 - 30))
                    wave_text = big_font.render(f"波次 {self.current_wave-1} 完成!", True, YELLOW)
                    surface.blit(wave_text, (SCREEN_WIDTH//2 - wave_text.get_width()//2, SCREEN_HEIGHT//2 - 20))
                else:
                    self.wave_completed = False
            
            # 游戏结束画面
            if self.game_over:
                game_over_surf = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
                game_over_surf.fill((0, 0, 0, 180))
                surface.blit(game_over_surf, (0, 0))
                
                if len(self.zombies) > 0:
                    game_over_text = big_font.render("游戏失败!", True, RED)
                else:
                    game_over_text = big_font.render("关卡完成!", True, GREEN)
                
                text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 80))
                surface.blit(game_over_text, text_rect)
                
                score_text = big_font.render(f"最终分数: {self.score}", True, WHITE)
                score_rect = score_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 30))
                surface.blit(score_text, score_rect)
                
                restart_text = font.render("按Enter键重新开始本关", True, WHITE)
                restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20))
                surface.blit(restart_text, restart_rect)
                
                menu_text = font.render("按ESC键返回主菜单", True, WHITE)
                menu_rect = menu_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 60))
                surface.blit(menu_text, menu_rect)
    
    def handle_click(self, pos):
        if self.state == "menu":
            # 开始游戏按钮
            start_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 200, 200, 60)
            if start_btn.collidepoint(pos):
                self.start_level(1)
            
            # 选择关卡按钮
            level_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 280, 200, 60)
            if level_btn.collidepoint(pos):
                self.state = "level_select"
            
            # 退出游戏按钮
            quit_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 360, 200, 60)
            if quit_btn.collidepoint(pos):
                pygame.quit()
                sys.exit()
        
        elif self.state == "level_select":
            # 关卡按钮
            for i in range(self.max_level):
                if i < self.unlocked_level:  # 只处理已解锁关卡
                    level_btn = pygame.Rect(150 + (i % 3) * 200, 150 + (i // 3) * 120, 150, 80)
                    if level_btn.collidepoint(pos):
                        self.start_level(i+1)
            
            # 返回主菜单按钮
            back_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 450, 200, 60)
            if back_btn.collidepoint(pos):
                self.state = "menu"
        
        elif self.state == "playing" and not self.game_over:
            # 返回主菜单按钮
            back_btn = pygame.Rect(LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 140, 140, 30)
            if back_btn.collidepoint(pos):
                self.state = "menu"
                return
            
            # 检查是否点击了铲子卡片
            if self.shovel_card["rect"].collidepoint(pos):
                self.shovel_selected = not self.shovel_selected
                if self.shovel_selected:
                    self.selected_plant = None
                return
            
            # 铲子功能
            if self.shovel_selected:
                for plant in self.plants[:]:
                    if plant.rect.collidepoint(pos):
                        self.plants.remove(plant)
                        self.shovel_selected = False
                        return
                self.shovel_selected = False
                return
            
            # 检查是否点击了阳光
            for sun in self.suns[:]:
                if sun.is_clicked(pos):
                    self.suns.remove(sun)
                    self.sun_count += sun.value
                    return
            
            # 检查是否点击了植物卡片
            for card in self.plant_cards:
                if card["rect"].collidepoint(pos) and self.sun_count >= card["cost"]:
                    self.selected_plant = card["type"]
                    self.shovel_selected = False
                    return
            
            # 检查是否在草坪上种植植物
            if self.selected_plant:
                x, y = pos
                # 检查点击位置是否在草坪网格内
                if (LAWN_LEFT <= x < LAWN_LEFT + GRID_WIDTH * GRID_SIZE and 
                    LAWN_TOP <= y < LAWN_TOP + GRID_HEIGHT * GRID_SIZE):
                    
                    # 计算网格位置
                    col = (x - LAWN_LEFT) // GRID_SIZE
                    row = (y - LAWN_TOP) // GRID_SIZE
                    plant_x = LAWN_LEFT + col * GRID_SIZE + GRID_SIZE // 2
                    plant_y = LAWN_TOP + row * GRID_SIZE + GRID_SIZE // 2
                    
                    # 检查该位置是否已有植物
                    plant_rect = pygame.Rect(plant_x - 30, plant_y - 30, 60, 60)
                    occupied = False
                    for plant in self.plants:
                        if plant_rect.colliderect(plant.rect):
                            occupied = True
                            break
                    
                    if not occupied:
                        # 找到选中的植物类型和成本
                        for card in self.plant_cards:
                            if card["type"] == self.selected_plant:
                                if self.sun_count >= card["cost"]:
                                    self.plants.append(Plant(plant_x, plant_y, self.selected_plant))
                                    self.sun_count -= card["cost"]
                                break
                self.selected_plant = None

def main():
    game = Game()
    
    running = True
    while running:
        # 处理事件
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            elif event.type == MOUSEBUTTONDOWN:
                if event.button == 1:  # 左键点击
                    game.handle_click(event.pos)
            elif event.type == KEYDOWN:
                if event.key == K_RETURN and game.state == "playing" and game.game_over:
                    game.start_level(game.level)
                elif event.key == K_ESCAPE:
                    if game.state == "playing" and game.game_over:
                        game.state = "menu"
                    elif game.state == "playing":
                        game.state = "menu"
                    elif game.state == "level_select":
                        game.state = "menu"
                elif event.key == K_q:  # 按Q键退出游戏
                    running = False
       
        # 更新游戏状态
        if game.state == "playing":
            game.update()
        
        # 绘制
        game.draw(screen)
        pygame.display.flip()
        
        # 控制帧率
        clock.tick(FPS)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()
点击查看代码
import pygame
import random
import sys
import os
import math
from pygame.locals import *

# 初始化pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 600
FPS = 60
GRID_SIZE = 80
GRID_WIDTH = 9
GRID_HEIGHT = 5
LAWN_LEFT = 150
LAWN_TOP = 100

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
BROWN = (139, 69, 19)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GRAY = (100, 100, 100)
PURPLE = (128, 0, 128)

# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("植物大战僵尸 - 优化版")
clock = pygame.time.Clock()

# 创建更复杂的图像
def create_complex_sun():
    surf = pygame.Surface((40, 40), pygame.SRCALPHA)
    pygame.draw.circle(surf, YELLOW, (20, 20), 20)
    for i in range(8):
        angle = i * 45
        end_x = 20 + 25 * pygame.math.Vector2(1, 0).rotate(angle).x
        end_y = 20 + 25 * pygame.math.Vector2(1, 0).rotate(angle).y
        pygame.draw.line(surf, YELLOW, (20, 20), (end_x, end_y), 3)
    pygame.draw.circle(surf, (255, 165, 0), (20, 20), 15)
    return surf

def create_complex_sunflower():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 茎
    pygame.draw.rect(surf, GREEN, (28, 30, 4, 30))
    # 花盆
    pygame.draw.rect(surf, BROWN, (20, 50, 20, 10))
    # 花心
    pygame.draw.circle(surf, (139, 69, 19), (30, 25), 15)
    # 花瓣
    for i in range(8):
        angle = i * 45
        end_x = 30 + 25 * pygame.math.Vector2(1, 0).rotate(angle).x
        end_y = 25 + 25 * pygame.math.Vector2(1, 0).rotate(angle).y
        pygame.draw.circle(surf, (255, 215, 0), (end_x, end_y), 10)
    # 笑脸
    pygame.draw.circle(surf, BLACK, (25, 20), 2)
    pygame.draw.circle(surf, BLACK, (35, 20), 2)
    pygame.draw.arc(surf, BLACK, (22, 25, 16, 10), 0.2, 2.9, 2)
    return surf

def create_complex_zombie():
    surf = pygame.Surface((50, 80), pygame.SRCALPHA)
    # 身体
    pygame.draw.ellipse(surf, (150, 150, 150), (10, 20, 30, 50))
    # 头
    pygame.draw.circle(surf, (200, 200, 200), (25, 20), 15)
    # 眼睛
    pygame.draw.circle(surf, (50, 50, 50), (20, 18), 3)
    pygame.draw.circle(surf, (50, 50, 50), (30, 18), 3)
    # 嘴巴
    pygame.draw.rect(surf, (100, 0, 0), (20, 25, 10, 3))
    # 衣服
    pygame.draw.rect(surf, (70, 70, 70), (10, 35, 30, 15))
    pygame.draw.line(surf, (100, 100, 100), (10, 42), (40, 42), 2)
    # 手臂
    pygame.draw.line(surf, (200, 200, 200), (10, 40), (0, 50), 5)
    pygame.draw.line(surf, (200, 200, 200), (40, 40), (50, 50), 5)
    # 腿
    pygame.draw.line(surf, (70, 70, 70), (20, 70), (20, 80), 5)
    pygame.draw.line(surf, (70, 70, 70), (30, 70), (30, 80), 5)
    # 僵尸标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("Z", True, RED)
    surf.blit(text, (40, 10))
    return surf

def create_complex_peashooter():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 茎
    pygame.draw.rect(surf, GREEN, (28, 30, 4, 30))
    # 花盆
    pygame.draw.rect(surf, BROWN, (20, 50, 20, 10))
    # 头部
    pygame.draw.circle(surf, GREEN, (30, 25), 15)
    # 嘴巴
    pygame.draw.circle(surf, (0, 100, 0), (35, 25), 8)
    # 眼睛
    pygame.draw.circle(surf, BLACK, (25, 20), 3)
    # 豌豆标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("P", True, (0, 100, 0))
    surf.blit(text, (20, 15))
    return surf

def create_complex_wallnut():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 坚果
    pygame.draw.ellipse(surf, BROWN, (10, 10, 40, 50))
    # 纹理
    pygame.draw.line(surf, (101, 67, 33), (20, 20), (40, 25), 2)
    pygame.draw.line(surf, (101, 67, 33), (25, 30), (35, 40), 2)
    pygame.draw.line(surf, (101, 67, 33), (30, 45), (20, 50), 2)
    # 表情
    pygame.draw.circle(surf, BLACK, (25, 30), 2)
    pygame.draw.circle(surf, BLACK, (35, 30), 2)
    pygame.draw.arc(surf, BLACK, (22, 35, 16, 10), 0.2, 2.9, 2)
    # 坚果标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("W", True, (101, 67, 33))
    surf.blit(text, (40, 20))
    return surf

def create_complex_pea():
    surf = pygame.Surface((20, 10), pygame.SRCALPHA)
    pygame.draw.ellipse(surf, (50, 200, 50), (0, 0, 20, 10))
    pygame.draw.ellipse(surf, (0, 100, 0), (5, 2, 10, 6))
    return surf

def create_complex_shovel():
    surf = pygame.Surface((40, 40), pygame.SRCALPHA)
    # 手柄
    pygame.draw.rect(surf, BROWN, (15, 5, 10, 20))
    # 铲头
    points = [(10, 25), (30, 25), (25, 40), (15, 40)]
    pygame.draw.polygon(surf, (180, 180, 180), points)
    return surf

def create_complex_pepper():
    surf = pygame.Surface((60, 60), pygame.SRCALPHA)
    # 茎
    pygame.draw.rect(surf, GREEN, (28, 30, 4, 30))
    # 花盆
    pygame.draw.rect(surf, BROWN, (20, 50, 20, 10))
    # 辣椒
    pygame.draw.ellipse(surf, RED, (15, 15, 30, 40))
    # 火焰效果
    for i in range(5):
        angle = random.randint(0, 360)
        length = random.randint(5, 15)
        end_x = 30 + length * math.cos(math.radians(angle))
        end_y = 30 + length * math.sin(math.radians(angle))
        pygame.draw.line(surf, (255, 165, 0), (30, 30), (end_x, end_y), 3)
    # 标识
    font = pygame.font.SysFont('Arial', 12, bold=True)
    text = font.render("F", True, WHITE)
    surf.blit(text, (45, 20))
    return surf

def create_lawnmower():
    surf = pygame.Surface((60, 40), pygame.SRCALPHA)
    # 车身
    pygame.draw.rect(surf, (50, 200, 50), (0, 10, 50, 20))
    # 轮子
    pygame.draw.circle(surf, BLACK, (10, 30), 8)
    pygame.draw.circle(surf, BLACK, (40, 30), 8)
    # 刀片
    pygame.draw.rect(surf, (200, 200, 200), (50, 15, 10, 10))
    return surf

# 创建更复杂的图像资源
sun_img = create_complex_sun()
sunflower_img = create_complex_sunflower()
peashooter_img = create_complex_peashooter()
wallnut_img = create_complex_wallnut()
zombie_img = create_complex_zombie()
pea_img = create_complex_pea()
shovel_img = create_complex_shovel()
pepper_img = create_complex_pepper()
lawnmower_img = create_lawnmower()

# 游戏字体
font = pygame.font.SysFont('Arial', 24)
big_font = pygame.font.SysFont('Arial', 36, bold=True)
title_font = pygame.font.SysFont('Arial', 48, bold=True)

class Sun:
    def __init__(self, x, y, is_falling=True):
        self.x = x
        self.y = y
        self.image = sun_img
        self.rect = self.image.get_rect(center=(x, y))
        self.value = 25
        self.speed = 2
        self.is_falling = is_falling
        self.collected = False
        self.fall_target_y = y + random.randint(100, 200)
        self.lifetime = 0
        self.max_lifetime = 10 * FPS  # 10秒
    
    def update(self):
        self.lifetime += 1
        if self.lifetime >= self.max_lifetime:
            self.collected = True
        
        if self.is_falling and self.y < self.fall_target_y:
            self.y += self.speed
            self.rect.center = (self.x, self.y)
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)
    
    def is_clicked(self, pos):
        return self.rect.collidepoint(pos) and not self.collected

class Plant:
    def __init__(self, x, y, plant_type):
        self.x = x
        self.y = y
        self.plant_type = plant_type
        self.health = 100
        self.attack_cooldown = 0
        self.eaten = False  # 是否正在被吃
        
        if plant_type == "peashooter":
            self.image = peashooter_img
            self.cost = 100
            self.attack_speed = 2 * FPS  # 每2秒攻击一次
        elif plant_type == "sunflower":
            self.image = sunflower_img
            self.cost = 50
            self.sun_production_speed = 10 * FPS  # 每10秒产生阳光
            self.sun_production_timer = 0
        elif plant_type == "wallnut":
            self.image = wallnut_img
            self.cost = 50
            self.health = 300  # 坚果墙有更多生命值
        elif plant_type == "pepper":
            self.image = pepper_img
            self.cost = 150
            self.exploded = False
        
        self.rect = self.image.get_rect(center=(x, y))
    
    def update(self):
        if self.plant_type == "peashooter":
            if self.attack_cooldown > 0:
                self.attack_cooldown -= 1
        elif self.plant_type == "sunflower":
            self.sun_production_timer += 1
            if self.sun_production_timer >= self.sun_production_speed:
                self.sun_production_timer = 0
                return True  # 表示应该产生阳光
        elif self.plant_type == "pepper":
            # 辣椒种植后立即爆炸
            if not self.exploded:
                self.exploded = True
                return "explode"
        return False
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)
        # 绘制生命条(辣椒不需要)
        if self.plant_type != "pepper":
            health_bar_width = 40
            health_ratio = self.health / (300 if self.plant_type == "wallnut" else 100)
            pygame.draw.rect(surface, RED, (self.x - health_bar_width//2, self.y - 40, health_bar_width, 5))
            pygame.draw.rect(surface, GREEN, (self.x - health_bar_width//2, self.y - 40, int(health_bar_width * health_ratio), 5))
    
    def can_attack(self):
        return self.plant_type == "peashooter" and self.attack_cooldown <= 0
    
    def attack(self):
        if self.plant_type == "peashooter":
            self.attack_cooldown = self.attack_speed
            return Pea(self.x + 30, self.y)
        return None

class Pea:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.image = pea_img
        self.rect = self.image.get_rect(center=(x, y))
        self.speed = 5
        self.damage = 20
    
    def update(self):
        self.x += self.speed
        self.rect.center = (self.x, self.y)
        return self.x > SCREEN_WIDTH  # 如果豌豆飞出屏幕则返回True
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)

class Zombie:
    def __init__(self, row, level):
        self.x = SCREEN_WIDTH
        self.y = LAWN_TOP + row * GRID_SIZE + GRID_SIZE // 2
        self.image = zombie_img
        self.rect = self.image.get_rect(midright=(self.x, self.y))
        # 僵尸速度随关卡增加而增加(初始速度降低)
        self.speed = 0.15 + level * 0.05
        self.health = 100 + level * 20  # 僵尸生命值随关卡增加
        self.damage = 0.5 + level * 0.1  # 僵尸伤害随关卡增加
        self.attack_cooldown = 0
        self.row = row
        self.walk_animation = 0
        self.walk_speed = 0.1
        self.eating = False  # 是否正在吃植物
        self.eat_timer = 0  # 吃植物计时器
        self.current_plant = None  # 当前正在吃的植物
    
    def update(self):
        # 如果正在吃植物,则停止移动
        if not self.eating:
            self.walk_animation += self.walk_speed
            if self.walk_animation >= 2:
                self.walk_animation = 0
            
            # 轻微左右摆动模拟走路
            swing_offset = 2 * math.sin(self.walk_animation * math.pi)
            self.x -= self.speed
            self.rect.midright = (self.x, self.y + swing_offset)
        
        # 吃植物计时
        if self.eating:
            self.eat_timer += 1
            
            # 坚果需要更长时间吃完
            eat_time = 3 * FPS if self.current_plant and self.current_plant.plant_type == "wallnut" else 1 * FPS
            
            if self.eat_timer >= eat_time:
                self.eating = False
                self.eat_timer = 0
                self.current_plant = None
        
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
    
    def start_eating(self, plant):
        """开始吃植物"""
        self.eating = True
        self.eat_timer = 0
        self.current_plant = plant
    
    def draw(self, surface):
        surface.blit(self.image, self.rect)
        # 绘制生命条
        health_bar_width = 40
        health_ratio = self.health / (100 + self.health * 0.2)
        pygame.draw.rect(surface, RED, (self.x - health_bar_width//2, self.y - 50, health_bar_width, 5))
        pygame.draw.rect(surface, GREEN, (self.x - health_bar_width//2, self.y - 50, int(health_bar_width * health_ratio), 5))
        
        # 如果正在吃植物,绘制吃植物状态
        if self.eating:
            eat_text = font.render("吃...", True, RED)
            surface.blit(eat_text, (self.x - 20, self.y - 70))
    
    def can_attack(self):
        return self.attack_cooldown <= 0
    
    def attack(self, plant):
        self.attack_cooldown = FPS  # 1秒攻击一次
        plant.health -= self.damage
        return plant.health <= 0  # 返回植物是否被摧毁

class Lawnmower:
    def __init__(self, row):
        self.row = row
        self.x = LAWN_LEFT - 30
        self.y = LAWN_TOP + row * GRID_SIZE + GRID_SIZE // 2
        self.image = lawnmower_img
        self.rect = self.image.get_rect(center=(self.x, self.y))
        self.active = False
        self.speed = 10
        self.used = False  # 是否已使用
    
    def activate(self):
        if not self.used:
            self.active = True
            self.used = True
    
    def update(self):
        if self.active:
            self.x += self.speed
            self.rect.center = (self.x, self.y)
            return self.x > SCREEN_WIDTH  # 如果小推车移出屏幕则返回True
        return False
    
    def draw(self, surface):
        if not self.active:
            surface.blit(self.image, self.rect)

class Game:
    def __init__(self):
        self.plants = []
        self.zombies = []
        self.suns = []
        self.peas = []
        self.sun_count = 150
        self.selected_plant = None
        self.game_over = False
        self.wave_timer = 0
        self.zombie_spawn_timer = 0
        self.sun_spawn_timer = 0
        self.sun_spawn_interval = 10 * FPS  # 10秒自动生成一个阳光
        self.score = 0
        self.level = 1
        self.max_level = 5
        self.unlocked_level = 1
        self.state = "menu"  # menu, level_select, playing, game_over
        self.shovel_selected = False
        self.lawnmowers = [Lawnmower(i) for i in range(GRID_HEIGHT)]
        self.zombies_killed_this_wave = 0
        self.zombies_to_spawn = 0
        self.wave_completed = False
        
        # 初始化关卡数据(减少第一关僵尸数量)
        self.level_data = [
            {"waves": 1, "zombies_per_wave": 3, "description": "新手训练营"},  # 第一关只有3个僵尸
            {"waves": 2, "zombies_per_wave": 8, "description": "僵尸入侵开始"},
            {"waves": 2, "zombies_per_wave": 12, "description": "僵尸大军来袭"},
            {"waves": 3, "zombies_per_wave": 15, "description": "僵尸狂潮"},
            {"waves": 3, "zombies_per_wave": 20, "description": "最终决战"}
        ]
        
        # 植物卡片
        self.plant_cards = [
            {"type": "sunflower", "cost": 50, "rect": pygame.Rect(10, 10, 60, 80)},
            {"type": "peashooter", "cost": 100, "rect": pygame.Rect(10, 100, 60, 80)},
        ]
        
        # 铲子卡片
        self.shovel_card = {"type": "shovel", "cost": 0, "rect": pygame.Rect(10, 280, 60, 80)}
    
    def start_level(self, level):
        self.level = level
        self.plants = []
        self.zombies = []
        self.suns = []
        self.peas = []
        self.sun_count = 150
        self.selected_plant = None
        self.game_over = False
        self.wave_timer = 0
        self.zombie_spawn_timer = 0
        self.sun_spawn_timer = 0
        self.score = 0
        self.shovel_selected = False
        self.lawnmowers = [Lawnmower(i) for i in range(GRID_HEIGHT)]
        self.zombies_killed_this_wave = 0
        self.current_wave = 1
        self.zombies_to_spawn = self.level_data[level-1]["zombies_per_wave"]
        self.wave_completed = False
        
        # 根据关卡解锁植物
        self.plant_cards = [
            {"type": "sunflower", "cost": 50, "rect": pygame.Rect(10, 10, 60, 80)},
            {"type": "peashooter", "cost": 100, "rect": pygame.Rect(10, 100, 60, 80)},
        ]
        
        if level >= 2:  # 第二关解锁坚果
            self.plant_cards.append({"type": "wallnut", "cost": 50, "rect": pygame.Rect(10, 190, 60, 80)})
        
        if level >= 4:  # 第四关解锁辣椒
            self.plant_cards.append({"type": "pepper", "cost": 150, "rect": pygame.Rect(10, 280, 60, 80)})
        
        self.state = "playing"
    
    def spawn_sun(self, x=None, y=None, is_falling=True):
        if x is None:
            x = random.randint(LAWN_LEFT, LAWN_LEFT + GRID_WIDTH * GRID_SIZE)
        if y is None and is_falling:
            y = 0
        self.suns.append(Sun(x, y, is_falling))
    
    def spawn_zombie(self):
        row = random.randint(0, GRID_HEIGHT - 1)
        self.zombies.append(Zombie(row, self.level))
        self.zombies_to_spawn -= 1
    
    def update(self):
        if self.game_over or self.state != "playing":
            return
        
        # 更新阳光
        for sun in self.suns[:]:
            sun.update()
            if sun.collected:
                self.suns.remove(sun)
        
        # 更新植物
        for plant in self.plants[:]:
            result = plant.update()
            if result == True:  # 向日葵产生阳光
                self.spawn_sun(plant.x, plant.y + 30, False)
            elif result == "explode":  # 辣椒爆炸
                # 消灭附近僵尸
                for zombie in self.zombies[:]:
                    if abs(zombie.y - plant.y) < 100 and abs(zombie.x - plant.x) < 200:
                        self.zombies.remove(zombie)
                        self.score += 10
                        self.zombies_killed_this_wave += 1
                # 移除辣椒
                self.plants.remove(plant)
            
            # 检查植物是否需要攻击
            if plant.can_attack():
                # 检查该行是否有僵尸
                plant_row = (plant.y - LAWN_TOP) // GRID_SIZE
                zombies_in_row = [z for z in self.zombies if z.row == plant_row and z.x > plant.x]
                
                if zombies_in_row:
                    pea = plant.attack()
                    if pea:
                        self.peas.append(pea)
        
        # 更新豌豆
        for pea in self.peas[:]:
            if pea.update():  # 如果豌豆飞出屏幕
                self.peas.remove(pea)
                continue
            
            # 检查豌豆是否击中僵尸
            for zombie in self.zombies[:]:
                if pea.rect.colliderect(zombie.rect):
                    zombie.health -= pea.damage
                    if zombie.health <= 0:
                        self.zombies.remove(zombie)
                        self.score += 10
                        self.zombies_killed_this_wave += 1
                    self.peas.remove(pea)
                    break
        
        # 更新僵尸
        for zombie in self.zombies[:]:
            # 如果僵尸没有在吃植物,检查是否碰到植物
            if not zombie.eating:
                plant_collision = None
                for plant in self.plants:
                    if zombie.rect.colliderect(plant.rect):
                        plant_collision = plant
                        break
                
                if plant_collision:
                    # 开始吃植物
                    zombie.start_eating(plant_collision)
            
            zombie.update()
            
            # 如果僵尸在吃植物,进行攻击
            if zombie.eating and zombie.current_plant:
                if zombie.can_attack():
                    plant_destroyed = zombie.attack(zombie.current_plant)
                    if plant_destroyed:
                        self.plants.remove(zombie.current_plant)
                        zombie.eating = False
                        zombie.current_plant = None
            else:
                # 检查僵尸是否到达小推车位置
                if zombie.x < LAWN_LEFT:
                    # 激活小推车
                    self.lawnmowers[zombie.row].activate()
        
        # 更新小推车
        for lawnmower in self.lawnmowers[:]:
            if lawnmower.update():  # 如果小推车移出屏幕
                self.lawnmowers.remove(lawnmower)
            else:
                # 检查小推车是否消灭僵尸
                if lawnmower.active:
                    for zombie in self.zombies[:]:
                        if zombie.row == lawnmower.row and abs(zombie.x - lawnmower.x) < 50:
                            self.zombies.remove(zombie)
                            self.score += 10
                            self.zombies_killed_this_wave += 1
        
        # 检查小推车是否失效
        for i, lawnmower in enumerate(self.lawnmowers):
            if lawnmower.used and not lawnmower.active:
                # 检查是否有僵尸越过失效的小推车
                for zombie in self.zombies:
                    if zombie.row == i and zombie.x < LAWN_LEFT:
                        self.game_over = True
        
        # 自动生成阳光
        self.sun_spawn_timer += 1
        if self.sun_spawn_timer >= self.sun_spawn_interval:
            self.sun_spawn_timer = 0
            self.spawn_sun()
        
        # 生成僵尸
        if self.zombies_to_spawn > 0:
            self.zombie_spawn_timer += 1
            spawn_interval = max(1, 60 - self.level * 5)  # 随关卡增加生成速度
            if self.zombie_spawn_timer >= spawn_interval:
                self.zombie_spawn_timer = 0
                self.spawn_zombie()
        
        # 检查波次是否完成
        if self.zombies_to_spawn == 0 and len(self.zombies) == 0:
            if self.current_wave < self.level_data[self.level-1]["waves"]:
                self.current_wave += 1
                self.zombies_to_spawn = self.level_data[self.level-1]["zombies_per_wave"]
                self.zombies_killed_this_wave = 0
                self.wave_completed = True
                self.wave_timer = 0
            else:
                # 完成所有波次
                self.game_over = True
                if self.level == self.unlocked_level and self.unlocked_level < self.max_level:
                    self.unlocked_level += 1
    
    def draw(self, surface):
        # 绘制背景
        surface.fill((135, 206, 235))  # 天空蓝
        
        if self.state == "menu":
            # 绘制主菜单
            title = title_font.render("植物大战僵尸", True, GREEN)
            surface.blit(title, (SCREEN_WIDTH//2 - title.get_width()//2, 100))
            
            start_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 200, 200, 60)
            pygame.draw.rect(surface, (100, 200, 100), start_btn)
            pygame.draw.rect(surface, BLACK, start_btn, 3)
            start_text = big_font.render("开始游戏", True, WHITE)
            surface.blit(start_text, (SCREEN_WIDTH//2 - start_text.get_width()//2, 215))
            
            level_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 280, 200, 60)
            pygame.draw.rect(surface, (100, 150, 200), level_btn)
            pygame.draw.rect(surface, BLACK, level_btn, 3)
            level_text = big_font.render("选择关卡", True, WHITE)
            surface.blit(level_text, (SCREEN_WIDTH//2 - level_text.get_width()//2, 295))
            
            quit_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 360, 200, 60)
            pygame.draw.rect(surface, (200, 100, 100), quit_btn)
            pygame.draw.rect(surface, BLACK, quit_btn, 3)
            quit_text = big_font.render("退出游戏", True, WHITE)
            surface.blit(quit_text, (SCREEN_WIDTH//2 - quit_text.get_width()//2, 375))
            
            # 绘制最高解锁关卡
            level_text = font.render(f"已解锁关卡: {self.unlocked_level}/{self.max_level}", True, BLACK)
            surface.blit(level_text, (SCREEN_WIDTH//2 - level_text.get_width()//2, 450))
            
        elif self.state == "level_select":
            # 绘制关卡选择界面
            title = title_font.render("选择关卡", True, GREEN)
            surface.blit(title, (SCREEN_WIDTH//2 - title.get_width()//2, 50))
            
            for i in range(self.max_level):
                unlocked = i < self.unlocked_level
                level_btn = pygame.Rect(150 + (i % 3) * 200, 150 + (i // 3) * 120, 150, 80)
                
                if unlocked:
                    pygame.draw.rect(surface, (100, 200, 100), level_btn)
                else:
                    pygame.draw.rect(surface, (150, 150, 150), level_btn)
                
                pygame.draw.rect(surface, BLACK, level_btn, 3)
                
                level_text = big_font.render(f"关卡 {i+1}", True, WHITE if unlocked else BLACK)
                surface.blit(level_text, (level_btn.x + 75 - level_text.get_width()//2, level_btn.y + 25))
                
                desc_text = font.render(self.level_data[i]["description"], True, BLACK)
                surface.blit(desc_text, (level_btn.x + 75 - desc_text.get_width()//2, level_btn.y + 55))
            
            back_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 450, 200, 60)
            pygame.draw.rect(surface, (200, 150, 100), back_btn)
            pygame.draw.rect(surface, BLACK, back_btn, 3)
            back_text = big_font.render("返回主菜单", True, WHITE)
            surface.blit(back_text, (SCREEN_WIDTH//2 - back_text.get_width()//2, 465))
            
        elif self.state == "playing":
            # 绘制草坪网格
            for row in range(GRID_HEIGHT):
                for col in range(GRID_WIDTH):
                    rect = pygame.Rect(
                        LAWN_LEFT + col * GRID_SIZE,
                        LAWN_TOP + row * GRID_SIZE,
                        GRID_SIZE,
                        GRID_SIZE
                    )
                    pygame.draw.rect(surface, (124, 252, 0), rect)
                    pygame.draw.rect(surface, BLACK, rect, 1)
            
            # 绘制小推车
            for lawnmower in self.lawnmowers:
                lawnmower.draw(surface)
            
            # 绘制植物卡片
            for card in self.plant_cards:
                color = (200, 200, 200) if self.sun_count >= card["cost"] else (100, 100, 100)
                pygame.draw.rect(surface, color, card["rect"])
                pygame.draw.rect(surface, BLACK, card["rect"], 2)
                
                if card["type"] == "sunflower":
                    plant_img = sunflower_img
                elif card["type"] == "peashooter":
                    plant_img = peashooter_img
                elif card["type"] == "wallnut":
                    plant_img = wallnut_img
                elif card["type"] == "pepper":
                    plant_img = pepper_img
                
                surface.blit(plant_img, (card["rect"].x + 10, card["rect"].y + 10))
                
                # 绘制成本
                cost_text = font.render(str(card["cost"]), True, BLACK)
                surface.blit(cost_text, (card["rect"].x + 20, card["rect"].y + 60))
            
            # 绘制铲子卡片
            shovel_color = (200, 150, 150) if self.shovel_selected else (200, 200, 200)
            pygame.draw.rect(surface, shovel_color, self.shovel_card["rect"])
            pygame.draw.rect(surface, BLACK, self.shovel_card["rect"], 2)
            surface.blit(shovel_img, (self.shovel_card["rect"].x + 10, self.shovel_card["rect"].y + 10))
            shovel_text = font.render("铲子", True, BLACK)
            surface.blit(shovel_text, (self.shovel_card["rect"].x + 10, self.shovel_card["rect"].y + 60))
            
            # 绘制选中的植物(跟随鼠标)
            if self.selected_plant:
                mouse_x, mouse_y = pygame.mouse.get_pos()
                if self.selected_plant == "sunflower":
                    plant_img = sunflower_img
                elif self.selected_plant == "peashooter":
                    plant_img = peashooter_img
                elif self.selected_plant == "wallnut":
                    plant_img = wallnut_img
                elif self.selected_plant == "pepper":
                    plant_img = pepper_img
                
                surface.blit(plant_img, (mouse_x - 30, mouse_y - 30))
            
            # 绘制植物
            for plant in self.plants:
                plant.draw(surface)
            
            # 绘制僵尸
            for zombie in self.zombies:
                zombie.draw(surface)
            
            # 绘制豌豆
            for pea in self.peas:
                pea.draw(surface)
            
            # 绘制阳光
            for sun in self.suns:
                sun.draw(surface)
            
            # 绘制游戏信息
            pygame.draw.rect(surface, (200, 200, 200, 180), (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 10, 10, 180, 120))
            pygame.draw.rect(surface, BLACK, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 10, 10, 180, 120), 2)
            
            # 绘制阳光计数
            sun_text = font.render(f"阳光: {self.sun_count}", True, BLACK)
            surface.blit(sun_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 20))
            
            # 绘制分数
            score_text = font.render(f"分数: {self.score}", True, BLACK)
            surface.blit(score_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 50))
            
            # 绘制关卡和波次信息
            level_text = font.render(f"关卡: {self.level}", True, BLACK)
            surface.blit(level_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 80))
            
            wave_text = font.render(f"波次: {self.current_wave}/{self.level_data[self.level-1]['waves']}", True, BLACK)
            surface.blit(wave_text, (LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 110))
            
            # 绘制返回按钮
            back_btn = pygame.Rect(LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 140, 140, 30)
            pygame.draw.rect(surface, (200, 100, 100), back_btn)
            pygame.draw.rect(surface, BLACK, back_btn, 2)
            back_text = font.render("返回主菜单", True, WHITE)
            surface.blit(back_text, (back_btn.x + 10, back_btn.y + 5))
            
            # 波次完成提示
            if self.wave_completed:
                self.wave_timer += 1
                if self.wave_timer < 3 * FPS:  # 显示3秒
                    wave_surf = pygame.Surface((300, 60), pygame.SRCALPHA)
                    wave_surf.fill((0, 0, 0, 150))
                    surface.blit(wave_surf, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT//2 - 30))
                    wave_text = big_font.render(f"波次 {self.current_wave-1} 完成!", True, YELLOW)
                    surface.blit(wave_text, (SCREEN_WIDTH//2 - wave_text.get_width()//2, SCREEN_HEIGHT//2 - 20))
                else:
                    self.wave_completed = False
            
            # 游戏结束画面
            if self.game_over:
                game_over_surf = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
                game_over_surf.fill((0, 0, 0, 180))
                surface.blit(game_over_surf, (0, 0))
                
                if len(self.zombies) > 0:
                    game_over_text = big_font.render("游戏失败!", True, RED)
                else:
                    game_over_text = big_font.render("关卡完成!", True, GREEN)
                
                text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 80))
                surface.blit(game_over_text, text_rect)
                
                score_text = big_font.render(f"最终分数: {self.score}", True, WHITE)
                score_rect = score_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 30))
                surface.blit(score_text, score_rect)
                
                restart_text = font.render("按Enter键重新开始本关", True, WHITE)
                restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20))
                surface.blit(restart_text, restart_rect)
                
                menu_text = font.render("按ESC键返回主菜单", True, WHITE)
                menu_rect = menu_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 60))
                surface.blit(menu_text, menu_rect)
    
    def handle_click(self, pos):
        if self.state == "menu":
            # 开始游戏按钮
            start_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 200, 200, 60)
            if start_btn.collidepoint(pos):
                self.start_level(1)
            
            # 选择关卡按钮
            level_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 280, 200, 60)
            if level_btn.collidepoint(pos):
                self.state = "level_select"
            
            # 退出游戏按钮
            quit_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 360, 200, 60)
            if quit_btn.collidepoint(pos):
                pygame.quit()
                sys.exit()
        
        elif self.state == "level_select":
            # 关卡按钮
            for i in range(self.max_level):
                if i < self.unlocked_level:  # 只处理已解锁关卡
                    level_btn = pygame.Rect(150 + (i % 3) * 200, 150 + (i // 3) * 120, 150, 80)
                    if level_btn.collidepoint(pos):
                        self.start_level(i+1)
            
            # 返回主菜单按钮
            back_btn = pygame.Rect(SCREEN_WIDTH//2 - 100, 450, 200, 60)
            if back_btn.collidepoint(pos):
                self.state = "menu"
        
        elif self.state == "playing" and not self.game_over:
            # 返回主菜单按钮
            back_btn = pygame.Rect(LAWN_LEFT + GRID_WIDTH * GRID_SIZE + 20, 140, 140, 30)
            if back_btn.collidepoint(pos):
                self.state = "menu"
                return
            
            # 检查是否点击了铲子卡片
            if self.shovel_card["rect"].collidepoint(pos):
                self.shovel_selected = not self.shovel_selected
                if self.shovel_selected:
                    self.selected_plant = None
                return
            
            # 铲子功能
            if self.shovel_selected:
                for plant in self.plants[:]:
                    if plant.rect.collidepoint(pos):
                        self.plants.remove(plant)
                        self.shovel_selected = False
                        return
                self.shovel_selected = False
                return
            
            # 检查是否点击了阳光
            for sun in self.suns[:]:
                if sun.is_clicked(pos):
                    self.suns.remove(sun)
                    self.sun_count += sun.value
                    return
            
            # 检查是否点击了植物卡片
            for card in self.plant_cards:
                if card["rect"].collidepoint(pos) and self.sun_count >= card["cost"]:
                    self.selected_plant = card["type"]
                    self.shovel_selected = False
                    return
            
            # 检查是否在草坪上种植植物
            if self.selected_plant:
                x, y = pos
                # 检查点击位置是否在草坪网格内
                if (LAWN_LEFT <= x < LAWN_LEFT + GRID_WIDTH * GRID_SIZE and 
                    LAWN_TOP <= y < LAWN_TOP + GRID_HEIGHT * GRID_SIZE):
                    
                    # 计算网格位置
                    col = (x - LAWN_LEFT) // GRID_SIZE
                    row = (y - LAWN_TOP) // GRID_SIZE
                    plant_x = LAWN_LEFT + col * GRID_SIZE + GRID_SIZE // 2
                    plant_y = LAWN_TOP + row * GRID_SIZE + GRID_SIZE // 2
                    
                    # 检查该位置是否已有植物
                    plant_rect = pygame.Rect(plant_x - 30, plant_y - 30, 60, 60)
                    occupied = False
                    for plant in self.plants:
                        if plant_rect.colliderect(plant.rect):
                            occupied = True
                            break
                    
                    if not occupied:
                        # 找到选中的植物类型和成本
                        for card in self.plant_cards:
                            if card["type"] == self.selected_plant:
                                if self.sun_count >= card["cost"]:
                                    self.plants.append(Plant(plant_x, plant_y, self.selected_plant))
                                    self.sun_count -= card["cost"]
                                break
                self.selected_plant = None

def main():
    game = Game()
    
    running = True
    while running:
        # 处理事件
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            elif event.type == MOUSEBUTTONDOWN:
                if event.button == 1:  # 左键点击
                    game.handle_click(event.pos)
            elif event.type == KEYDOWN:
                if event.key == K_RETURN and game.state == "playing" and game.game_over:
                    game.start_level(game.level)
                elif event.key == K_ESCAPE:
                    if game.state == "playing" and game.game_over:
                        game.state = "menu"
                    elif game.state == "playing":
                        game.state = "menu"
                    elif game.state == "level_select":
                        game.state = "menu"
                elif event.key == K_q:  # 按Q键退出游戏
                    running = False
        
        # 更新游戏状态
        if game.state == "playing":
            game.update()
        
        # 绘制
        game.draw(screen)
        pygame.display.flip()
        
        # 控制帧率
        clock.tick(FPS)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()
posted @ 2025-06-22 15:04  昔桯  阅读(54)  评论(0)    收藏  举报