点击查看代码
import pygame
import random
import sys

# 初始化pygame
pygame.init()

# 屏幕设置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("植物大战僵尸简化版 - 学号后四位: 3034")

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

# 游戏参数
FPS = 60
clock = pygame.time.Clock()

# 草坪网格
GRID_SIZE = 80
GRID_ROWS = 5
GRID_COLS = 9
LAWN_LEFT = 100
LAWN_TOP = 100

# 植物类
class Plant:
    def __init__(self, row, col):
        self.row = row
        self.col = col
        self.health = 100
        self.x = LAWN_LEFT + col * GRID_SIZE
        self.y = LAWN_TOP + row * GRID_SIZE
        self.attack_cooldown = 0
    
    def draw(self):
        pygame.draw.circle(screen, GREEN, (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2), 30)
    
    def update(self):
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
    
    def can_attack(self):
        return self.attack_cooldown == 0
    
    def attack(self):
        self.attack_cooldown = 60  # 1秒冷却
        return Projectile(self.row, self.col)

# 豌豆射手
class Peashooter(Plant):
    def __init__(self, row, col):
        super().__init__(row, col)
        self.health = 150
    
    def draw(self):
        pygame.draw.circle(screen, GREEN, (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2), 30)
        pygame.draw.circle(screen, BLACK, (self.x + GRID_SIZE//2 + 15, self.y + GRID_SIZE//2 - 10), 5)

# 向日葵
class Sunflower(Plant):
    def __init__(self, row, col):
        super().__init__(row, col)
        self.health = 100
        self.sun_cooldown = 0
    
    def draw(self):
        pygame.draw.circle(screen, (255, 255, 0), (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2), 30)
    
    def update(self):
        super().update()
        if self.sun_cooldown > 0:
            self.sun_cooldown -= 1
        else:
            self.sun_cooldown = 300  # 5秒产生阳光
            return Sun(self.x, self.y)
        return None

# 坚果墙
class WallNut(Plant):
    def __init__(self, row, col):
        super().__init__(row, col)
        self.health = 400
    
    def draw(self):
        pygame.draw.circle(screen, BROWN, (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2), 30)

# 僵尸类
class Zombie:
    def __init__(self, row):
        self.row = row
        self.col = GRID_COLS - 1
        self.x = LAWN_LEFT + self.col * GRID_SIZE
        self.y = LAWN_TOP + row * GRID_SIZE
        self.health = 200
        self.speed = 0.5
        self.attack_cooldown = 0
    
    def draw(self):
        pygame.draw.rect(screen, RED, (self.x, self.y, GRID_SIZE, GRID_SIZE))
    
    def update(self, plants):
        # 检查前方是否有植物
        attacking = False
        for plant in plants:
            if plant.row == self.row and plant.col == self.col:
                attacking = True
                if self.attack_cooldown == 0:
                    plant.health -= 10
                    self.attack_cooldown = 30
                else:
                    self.attack_cooldown -= 1
                break
        
        if not attacking:
            self.x -= self.speed
            self.col = int((self.x - LAWN_LEFT) / GRID_SIZE)
        
        return self.x < LAWN_LEFT  # 是否到达最左边(游戏失败)

# 阳光类
class Sun:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.target_y = y + random.randint(50, 150)
        self.speed = 1
        self.collected = False
        self.value = 25
    
    def draw(self):
        pygame.draw.circle(screen, (255, 255, 0), (self.x + GRID_SIZE//2, self.y), 20)
    
    def update(self):
        if self.y < self.target_y:
            self.y += self.speed
        return self.collected

# 豌豆子弹
class Projectile:
    def __init__(self, row, col):
        self.row = row
        self.col = col
        self.x = LAWN_LEFT + col * GRID_SIZE + GRID_SIZE
        self.y = LAWN_TOP + row * GRID_SIZE + GRID_SIZE//2
        self.speed = 5
        self.damage = 20
    
    def draw(self):
        pygame.draw.circle(screen, GREEN, (self.x, self.y), 5)
    
    def update(self):
        self.x += self.speed
        return self.x > SCREEN_WIDTH  # 是否飞出屏幕

# 游戏主类
class Game:
    def __init__(self):
        self.plants = []
        self.zombies = []
        self.projectiles = []
        self.suns = []
        self.sun_count = 100
        self.selected_plant = None
        self.game_over = False
        self.zombie_spawn_timer = 0
        self.font = pygame.font.SysFont(None, 36)
    
    def draw_lawn(self):
        # 绘制草坪网格
        for row in range(GRID_ROWS):
            for col in range(GRID_COLS):
                rect = pygame.Rect(LAWN_LEFT + col * GRID_SIZE, 
                                  LAWN_TOP + row * GRID_SIZE, 
                                  GRID_SIZE, GRID_SIZE)
                pygame.draw.rect(screen, (144, 238, 144), rect, 1)
    
    def draw_ui(self):
        # 绘制阳光数量
        sun_text = self.font.render(f"阳光: {self.sun_count}", True, BLACK)
        screen.blit(sun_text, (20, 20))
        
        # 绘制植物选择菜单
        pygame.draw.rect(screen, GREEN, (20, 60, 60, 60))
        pygame.draw.rect(screen, (255, 255, 0), (90, 60, 60, 60))
        pygame.draw.rect(screen, BROWN, (160, 60, 60, 60))
        
        # 显示游戏结束
        if self.game_over:
            game_over_text = self.font.render("游戏结束! 按R键重新开始", True, RED)
            screen.blit(game_over_text, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT//2))
    
    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            
            if event.type == pygame.MOUSEBUTTONDOWN:
                mouse_x, mouse_y = pygame.mouse.get_pos()
                
                # 检查是否点击了植物选择菜单
                if 20 <= mouse_x <= 80 and 60 <= mouse_y <= 120:
                    self.selected_plant = "peashooter"
                elif 90 <= mouse_x <= 150 and 60 <= mouse_y <= 120:
                    self.selected_plant = "sunflower"
                elif 160 <= mouse_x <= 220 and 60 <= mouse_y <= 120:
                    self.selected_plant = "wallnut"
                
                # 检查是否点击了草坪
                if (LAWN_LEFT <= mouse_x <= LAWN_LEFT + GRID_COLS * GRID_SIZE and 
                    LAWN_TOP <= mouse_y <= LAWN_TOP + GRID_ROWS * GRID_SIZE):
                    col = (mouse_x - LAWN_LEFT) // GRID_SIZE
                    row = (mouse_y - LAWN_TOP) // GRID_SIZE
                    
                    # 检查该位置是否已有植物
                    position_empty = True
                    for plant in self.plants:
                        if plant.row == row and plant.col == col:
                            position_empty = False
                            break
                    
                    if position_empty and self.selected_plant:
                        cost = 0
                        if self.selected_plant == "peashooter":
                            cost = 100
                        elif self.selected_plant == "sunflower":
                            cost = 50
                        elif self.selected_plant == "wallnut":
                            cost = 75
                        
                        if self.sun_count >= cost:
                            self.sun_count -= cost
                            if self.selected_plant == "peashooter":
                                self.plants.append(Peashooter(row, col))
                            elif self.selected_plant == "sunflower":
                                self.plants.append(Sunflower(row, col))
                            elif self.selected_plant == "wallnut":
                                self.plants.append(WallNut(row, col))
                
                # 检查是否点击了阳光
                for sun in self.suns:
                    if (abs(mouse_x - (sun.x + GRID_SIZE//2)) < 20 and 
                        abs(mouse_y - sun.y) < 20):
                        sun.collected = True
                        self.sun_count += sun.value
            
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r and self.game_over:
                    self.__init__()  # 重置游戏
    
    def update(self):
        if self.game_over:
            return
        
        # 生成僵尸
        self.zombie_spawn_timer += 1
        if self.zombie_spawn_timer >= 300:  # 每5秒生成一个僵尸
            self.zombie_spawn_timer = 0
            row = random.randint(0, GRID_ROWS - 1)
            self.zombies.append(Zombie(row))
        
        # 更新植物
        for plant in self.plants[:]:
            plant.update()
            
            if isinstance(plant, Sunflower):
                sun = plant.update()
                if sun:
                    self.suns.append(sun)
            
            if plant.health <= 0:
                self.plants.remove(plant)
            elif plant.can_attack() and isinstance(plant, Peashooter):
                # 检查该行是否有僵尸
                for zombie in self.zombies:
                    if zombie.row == plant.row and zombie.col > plant.col:
                        self.projectiles.append(plant.attack())
                        break
        
        # 更新僵尸
        for zombie in self.zombies[:]:
            if zombie.update(self.plants):
                self.game_over = True
            if zombie.health <= 0:
                self.zombies.remove(zombie)
        
        # 更新子弹
        for projectile in self.projectiles[:]:
            if projectile.update():
                self.projectiles.remove(projectile)
            else:
                # 检查是否击中僵尸
                for zombie in self.zombies:
                    if (zombie.row == projectile.row and 
                        zombie.x <= projectile.x <= zombie.x + GRID_SIZE):
                        zombie.health -= projectile.damage
                        self.projectiles.remove(projectile)
                        break
        
        # 更新阳光
        for sun in self.suns[:]:
            if sun.update():
                self.suns.remove(sun)
        
        # 随机生成阳光
        if random.random() < 0.005:  # 0.5%的几率每帧生成阳光
            x = random.randint(LAWN_LEFT, LAWN_LEFT + GRID_COLS * GRID_SIZE)
            self.suns.append(Sun(x, 0))
    
    def draw(self):
        screen.fill(WHITE)
        self.draw_lawn()
        
        # 绘制植物
        for plant in self.plants:
            plant.draw()
        
        # 绘制僵尸
        for zombie in self.zombies:
            zombie.draw()
        
        # 绘制子弹
        for projectile in self.projectiles:
            projectile.draw()
        
        # 绘制阳光
        for sun in self.suns:
            sun.draw()
        
        self.draw_ui()
        
        # 显示选中的植物
        if self.selected_plant:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            if self.selected_plant == "peashooter":
                pygame.draw.circle(screen, GREEN, (mouse_x, mouse_y), 30)
            elif self.selected_plant == "sunflower":
                pygame.draw.circle(screen, (255, 255, 0), (mouse_x, mouse_y), 30)
            elif self.selected_plant == "wallnut":
                pygame.draw.circle(screen, BROWN, (mouse_x, mouse_y), 30)
        
        pygame.display.flip()

# 主游戏循环
def main():
    game = Game()
    while True:
        game.handle_events()
        game.update()
        game.draw()
        clock.tick(FPS)

if __name__ == "__main__":
    main()
posted on 2025-06-23 13:05  986614  阅读(22)  评论(0)    收藏  举报