import pygame
import random
import sys
# 初始化游戏
pygame.init()
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("简易植物大战僵尸")
clock = pygame.time.Clock()
FPS = 30
# 颜色定义
GREEN = (0, 200, 0)
LIGHT_GREEN = (0, 255, 0)
BROWN = (139, 69, 19)
YELLOW = (255, 255, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
# 游戏参数
GRID_SIZE = 80
ROW_NUM, COL_NUM = 5, 9
SUN_VALUE = 25
PLANT_COST = {"sunflower": 50, "peashooter": 100}
ZOMBIE_HP = 100
PEA_DAMAGE = 20
# 字体
font = pygame.font.SysFont('simhei', 24) # 确保中文显示
# 绘制网格
def draw_grid():
for row in range(ROW_NUM):
for col in range(COL_NUM):
x, y = col * GRID_SIZE, row * GRID_SIZE
if (row + col) % 2 == 0:
pygame.draw.rect(screen, GREEN, (x, y, GRID_SIZE, GRID_SIZE))
else:
pygame.draw.rect(screen, LIGHT_GREEN, (x, y, GRID_SIZE, GRID_SIZE))
pygame.draw.rect(screen, (50, 50, 50), (x, y, GRID_SIZE, GRID_SIZE), 1) # 网格线
# 阳光类
class Sun:
def __init__(self):
self.x = random.randint(50, width - 50)
self.y = -50
self.radius = 15
self.speed = 1
self.value = SUN_VALUE
self.collected = False
def update(self):
self.y += self.speed
if self.y > height:
return True
return False
def draw(self):
pygame.draw.circle(screen, YELLOW, (self.x, self.y), self.radius)
pygame.draw.circle(screen, (255, 200, 0), (self.x, self.y), self.radius // 2)
# 植物类
class Plant:
def __init__(self, type_, row, col, sun_count):
self.type = type_
self.row = row
self.col = col
self.x = col * GRID_SIZE + GRID_SIZE // 2
self.y = row * GRID_SIZE + GRID_SIZE // 2
self.hp = 100
self.cost = PLANT_COST[type_]
self.last_attack = pygame.time.get_ticks()
self.attack_interval = 2000 if type_ == "peashooter" else 5000 # 攻击间隔(毫秒)
def update(self, peas):
current_time = pygame.time.get_ticks()
if self.type == "sunflower" and current_time - self.last_attack > self.attack_interval:
self.last_attack = current_time
return Sun()
elif self.type == "peashooter" and current_time - self.last_attack > self.attack_interval:
self.last_attack = current_time
pea_x = self.x + GRID_SIZE // 2
pea_y = self.y
peas.append([pea_x, pea_y, self.row])
return None
def draw(self):
if self.type == "sunflower":
pygame.draw.circle(screen, YELLOW, (self.x, self.y), 25)
pygame.draw.circle(screen, (255, 150, 0), (self.x, self.y), 15)
else: # peashooter
pygame.draw.rect(screen, (0, 100, 0), (self.x - 15, self.y - 25, 30, 50))
pygame.draw.rect(screen, (0, 200, 0), (self.x - 10, self.y - 20, 20, 10)) # 叶子
pygame.draw.rect(screen, (0, 200, 0), (self.x + 5, self.y - 20, 20, 10))
pygame.draw.circle(screen, (0, 150, 0), (self.x, self.y - 30), 15) # 头部
# 豌豆类
class Pea:
def __init__(self, x, y, row):
self.x = x
self.y = y
self.row = row
self.speed = 3
self.remove = False
def update(self, zombies):
self.x += self.speed
if self.x > width:
self.remove = True
for zombie in zombies:
if zombie.row == self.row and zombie.x < self.x < zombie.x + 30 and zombie.y < self.y < zombie.y + 40:
zombie.hp -= PEA_DAMAGE
self.remove = True
break
def draw(self):
pygame.draw.circle(screen, (0, 255, 0), (self.x, self.y), 8)
# 僵尸类
class Zombie:
def __init__(self, row):
self.row = row
self.x = width
self.y = row * GRID_SIZE + GRID_SIZE // 2
self.hp = ZOMBIE_HP
self.speed = 0.5
self.remove = False
self.eaten = False
def update(self, plants):
self.x -= self.speed
if self.x < 0:
self.remove = True
self.eaten = True
# 检查是否碰到植物
for plant in plants:
if plant.row == self.row and self.x - 30 < plant.x < self.x:
plant.hp -= 1
if plant.hp <= 0:
plants.remove(plant)
return self.eaten
def draw(self):
pygame.draw.rect(screen, (100, 0, 0), (self.x - 15, self.y - 20, 30, 40)) # 僵尸身体
pygame.draw.circle(screen, (150, 0, 0), (self.x, self.y - 30), 15) # 僵尸头
pygame.draw.rect(screen, (200, 0, 0), (self.x - 5, self.y - 15, 5, 10)) # 眼睛
pygame.draw.rect(screen, (200, 0, 0), (self.x + 5, self.y - 15, 5, 10))
# 游戏主循环
def main():
suns = [Sun() for _ in range(2)] # 初始阳光
plants = []
peas = []
zombies = []
sun_count = 50
selected_plant = None
game_over = False
win = False
while True:
screen.fill(BROWN) # 背景
draw_grid() # 绘制草坪网格
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN and not game_over:
if event.button == 1: # 左键点击
x, y = event.pos
# 收集阳光
for sun in suns:
if (sun.x - sun.radius) < x < (sun.x + sun.radius) and \
(sun.y - sun.radius) < y < (sun.y + sun.radius):
sun_count += sun.value
suns.remove(sun)
suns.append(Sun()) # 生成新阳光
break
# 种植植物
if selected_plant and sun_count >= PLANT_COST[selected_plant]:
row, col = y // GRID_SIZE, x // GRID_SIZE
if 0 <= row < ROW_NUM and 0 <= col < COL_NUM:
# 检查是否已有植物
if not any(plant.row == row and plant.col == col for plant in plants):
plants.append(Plant(selected_plant, row, col, sun_count))
sun_count -= PLANT_COST[selected_plant]
if event.type == pygame.KEYDOWN and not game_over:
if event.key == pygame.K_1 and sun_count >= PLANT_COST["peashooter"]:
selected_plant = "peashooter"
if event.key == pygame.K_2 and sun_count >= PLANT_COST["sunflower"]:
selected_plant = "sunflower"
if event.key == pygame.K_r: # 重新开始
main()
# 显示选中的植物
if selected_plant == "peashooter":
pygame.draw.rect(screen, YELLOW, (10, 10, 60, 60), 2)
plant = Plant("peashooter", 0, 0, 0)
plant.draw()
elif selected_plant == "sunflower":
pygame.draw.rect(screen, YELLOW, (10, 10, 60, 60), 2)
plant = Plant("sunflower", 0, 0, 0)
plant.draw()
# 绘制植物选择框
plant1 = Plant("peashooter", 0, 0, 0)
plant1.draw()
plant1.x, plant1.y = 10, 10
cost1 = font.render(f"100", True, WHITE)
screen.blit(cost1, (10, 70))
plant2 = Plant("sunflower", 0, 0, 0)
plant2.draw()
plant2.x, plant2.y = 80, 10
cost2 = font.render(f"50", True, WHITE)
screen.blit(cost2, (80, 70))
# 生成阳光
if random.random() < 0.005 and len(suns) < 5:
suns.append(Sun())
# 生成僵尸
if random.random() < 0.002 and len(zombies) < 3:
zombies.append(Zombie(random.randint(0, ROW_NUM-1)))
# 更新和绘制阳光
for sun in suns[:]:
if sun.update():
suns.remove(sun)
sun.draw()
# 更新和绘制植物
new_suns = []
for plant in plants[:]:
new_sun = plant.update(peas)
if new_sun:
new_suns.append(new_sun)
plant.draw()
if plant.hp <= 0:
plants.remove(plant)
suns.extend(new_suns)
# 更新和绘制豌豆
for pea in peas[:]:
pea.update(zombies)
if pea.remove:
peas.remove(pea)
pea.draw()
# 更新和绘制僵尸
game_over = False
for zombie in zombies[:]:
if zombie.update(plants):
game_over = True
zombie.draw()
if zombie.hp <= 0:
zombies.remove(zombie)
if game_over:
overlay = pygame.Surface((width, height), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 180))
screen.blit(overlay, (0, 0))
text = font.render("游戏结束! 按R键重新开始", True, WHITE)
screen.blit(text, (width//2 - 150, height//2))
# 检查胜利条件
if not zombies and len(plants) > 0:
win = True
overlay = pygame.Surface((width, height), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 180))
screen.blit(overlay, (0, 0))
text = font.render("游戏胜利! 按R键重新开始", True, WHITE)
screen.blit(text, (width//2 - 150, height//2))
# 显示阳光数量
sun_text = font.render(f"阳光: {sun_count}", True, WHITE)
screen.blit(sun_text, (width - 120, 10))
pygame.display.flip()
clock.tick(FPS)
if __name__ == "__main__":
main()
![]()