植物大战僵尸简易版
import pygame
import random
import sys
special_number = 3028
初始化pygame
pygame.init()
游戏窗口设置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("植物大战僵尸简易版 ")
颜色定义
GREEN = (0, 255, 0)
BROWN = (139, 69, 19)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
游戏参数
FPS = 60
clock = pygame.time.Clock()
草坪网格设置
GRID_SIZE = 80
GRID_COLS = 9
GRID_ROWS = 5
GRID_OFFSET_X = 50
GRID_OFFSET_Y = 100
植物类
class Plant:
def init(self, row, col):
self.row = row
self.col = col
self.x = GRID_OFFSET_X + col * GRID_SIZE
self.y = GRID_OFFSET_Y + row * GRID_SIZE
self.health = 100
self.attack_cooldown = 0
def update(self):
if self.attack_cooldown > 0:
self.attack_cooldown -= 1
def draw(self, surface):
pygame.draw.circle(surface, GREEN, (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2), 30)
# 绘制血条
pygame.draw.rect(surface, RED, (self.x, self.y - 10, GRID_SIZE, 5))
pygame.draw.rect(surface, GREEN, (self.x, self.y - 10, GRID_SIZE * (self.health/100), 5))
豌豆射手类
class Peashooter(Plant):
def init(self, row, col):
super().init(row, col)
self.attack_speed = 30 # 攻击速度
def can_shoot(self):
if self.attack_cooldown <= 0:
self.attack_cooldown = self.attack_speed
return True
return False
def draw(self, surface):
pygame.draw.circle(surface, GREEN, (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2), 30)
# 绘制枪管
pygame.draw.rect(surface, GREEN, (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2 - 5, 30, 10))
# 血条
pygame.draw.rect(surface, RED, (self.x, self.y - 10, GRID_SIZE, 5))
pygame.draw.rect(surface, GREEN, (self.x, self.y - 10, GRID_SIZE * (self.health/100), 5))
向日葵类
class Sunflower(Plant):
def init(self, row, col):
super().init(row, col)
self.sun_produce_cooldown = 200 # 生产阳光的冷却时间
def update(self):
if self.sun_produce_cooldown > 0:
self.sun_produce_cooldown -= 1
return False
else:
self.sun_produce_cooldown = 200
return True
def draw(self, surface):
pygame.draw.circle(surface, YELLOW, (self.x + GRID_SIZE//2, self.y + GRID_SIZE//2), 30)
# 绘制花瓣
for i in range(8):
angle = i * 45
end_x = self.x + GRID_SIZE//2 + 40 * pygame.math.Vector2(1, 0).rotate(angle).x
end_y = self.y + GRID_SIZE//2 + 40 * pygame.math.Vector2(1, 0).rotate(angle).y
pygame.draw.line(surface, YELLOW,
(self.x + GRID_SIZE//2, self.y + GRID_SIZE//2),
(end_x, end_y), 5)
# 血条
pygame.draw.rect(surface, RED, (self.x, self.y - 10, GRID_SIZE, 5))
pygame.draw.rect(surface, GREEN, (self.x, self.y - 10, GRID_SIZE * (self.health/100), 5))
豌豆类
class Pea:
def init(self, x, y):
self.x = x
self.y = y
self.speed = 5
self.damage = 20
def update(self):
self.x += self.speed
def draw(self, surface):
pygame.draw.circle(surface, GREEN, (self.x, self.y), 10)
def is_off_screen(self):
return self.x > SCREEN_WIDTH
阳光类
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.lifetime = 300 # 存在时间
self.collected = False
def update(self):
if self.y < self.target_y:
self.y += self.speed
self.lifetime -= 1
def draw(self, surface):
pygame.draw.circle(surface, YELLOW, (self.x, self.y), 20)
def is_dead(self):
return self.lifetime <= 0 or self.collected
僵尸类 (修改了速度)
class Zombie:
def init(self, row):
self.row = row
self.x = SCREEN_WIDTH
self.y = GRID_OFFSET_Y + row * GRID_SIZE + GRID_SIZE//2
self.speed = 0.5 + random.random() * 0.2 # 基础速度从1降到0.5,并添加随机波动
self.health = 100
self.damage = 0.5
def update(self):
self.x -= self.speed
def draw(self, surface):
pygame.draw.rect(surface, BROWN, (self.x - 30, self.y - 50, 60, 80))
# 绘制血条
pygame.draw.rect(surface, RED, (self.x - 30, self.y - 70, 60, 10))
pygame.draw.rect(surface, GREEN, (self.x - 30, self.y - 70, 60 * (self.health/100), 10))
def is_dead(self):
return self.health <= 0
def is_at_house(self):
return self.x <= 30
植物卡片类
class PlantCard:
def init(self, x, y, plant_type, cost):
self.x = x
self.y = y
self.width = 80
self.height = 100
self.plant_type = plant_type
self.cost = cost
self.cooldown = 0
self.cooldown_max = 100 if plant_type == "peashooter" else 150
def draw(self, surface, sun_count, selected=False):
# 绘制卡片背景
color = (100, 100, 100) if sun_count < self.cost else (200, 200, 200)
if selected:
color = (255, 255, 0) if sun_count >= self.cost else (150, 150, 0)
pygame.draw.rect(surface, color, (self.x, self.y, self.width, self.height))
pygame.draw.rect(surface, (50, 50, 50), (self.x, self.y, self.width, self.height), 2)
# 绘制植物图标
if self.plant_type == "peashooter":
pygame.draw.circle(surface, GREEN, (self.x + self.width//2, self.y + 40), 20)
pygame.draw.rect(surface, GREEN, (self.x + self.width//2, self.y + 40 - 5, 20, 10))
elif self.plant_type == "sunflower":
pygame.draw.circle(surface, YELLOW, (self.x + self.width//2, self.y + 40), 20)
for i in range(8):
angle = i * 45
end_x = self.x + self.width//2 + 25 * pygame.math.Vector2(1, 0).rotate(angle).x
end_y = self.y + 40 + 25 * pygame.math.Vector2(1, 0).rotate(angle).y
pygame.draw.line(surface, YELLOW,
(self.x + self.width//2, self.y + 40),
(end_x, end_y), 3)
# 绘制冷却效果
if self.cooldown > 0:
height = (self.cooldown / self.cooldown_max) * self.height
s = pygame.Surface((self.width, height), pygame.SRCALPHA)
s.fill((0, 0, 0, 180))
surface.blit(s, (self.x, self.y))
# 绘制阳光消耗
font = pygame.font.SysFont(None, 24)
cost_text = font.render(str(self.cost), True, YELLOW)
surface.blit(cost_text, (self.x + 10, self.y + self.height - 25))
def update(self):
if self.cooldown > 0:
self.cooldown -= 1
def is_clicked(self, pos):
x, y = pos
return (self.x <= x <= self.x + self.width and
self.y <= y <= self.y + self.height)
def is_ready(self, sun_count):
return self.cooldown <= 0 and sun_count >= self.cost
游戏类
class Game:
def init(self):
self.plants = []
self.zombies = []
self.peas = []
self.suns = []
self.sun = 75 # 初始阳光值
self.zombie_spawn_cooldown = 0
self.font = pygame.font.SysFont(None, 36)
self.selected_plant = None
self.game_over = False
# 创建植物卡片
self.plant_cards = [
PlantCard(10, 10, "peashooter", 100),
PlantCard(100, 10, "sunflower", 50)
]
def add_plant(self, row, col, plant_type):
# 检查该位置是否已有植物
for plant in self.plants:
if plant.row == row and plant.col == col:
return False
if plant_type == "peashooter":
self.plants.append(Peashooter(row, col))
return True
elif plant_type == "sunflower":
self.plants.append(Sunflower(row, col))
return True
return False
def add_zombie(self):
row = random.randint(0, GRID_ROWS - 1)
self.zombies.append(Zombie(row))
def add_sun(self, x=None, y=None):
if x is None and y is None:
# 随机位置生成阳光
x = random.randint(50, SCREEN_WIDTH - 50)
y = 0
self.suns.append(Sun(x, y))
def update(self):
if self.game_over:
return
# 更新植物卡片
for card in self.plant_cards:
card.update()
# 更新植物
for plant in self.plants:
if isinstance(plant, Peashooter):
plant.update()
if plant.can_shoot():
self.peas.append(Pea(plant.x + GRID_SIZE, plant.y + GRID_SIZE//2))
elif isinstance(plant, Sunflower):
if plant.update(): # 如果返回True,表示可以生产阳光
self.add_sun(plant.x + GRID_SIZE//2, plant.y + GRID_SIZE//2)
# 更新豌豆
for pea in self.peas[:]:
pea.update()
if pea.is_off_screen():
self.peas.remove(pea)
continue
# 检测豌豆是否击中僵尸
for zombie in self.zombies:
if (zombie.row == (pea.y - GRID_OFFSET_Y) // GRID_SIZE and
zombie.x - 30 <= pea.x <= zombie.x + 30):
zombie.health -= pea.damage
if pea in self.peas:
self.peas.remove(pea)
break
# 更新阳光
for sun in self.suns[:]:
sun.update()
if sun.is_dead():
self.suns.remove(sun)
# 更新僵尸
for zombie in self.zombies[:]:
zombie.update()
# 检测僵尸是否到达房子
if zombie.is_at_house():
self.game_over = True
return
# 检测僵尸是否死亡
if zombie.is_dead():
self.zombies.remove(zombie)
self.sun += 25 # 杀死僵尸获得阳光
continue
# 检测僵尸是否碰到植物
for plant in self.plants[:]:
if (zombie.row == plant.row and
plant.x <= zombie.x - 30 <= plant.x + GRID_SIZE):
plant.health -= zombie.damage
if plant.health <= 0:
self.plants.remove(plant)
# 随机生成僵尸 (增加了生成间隔)
if self.zombie_spawn_cooldown <= 0:
self.add_zombie()
self.zombie_spawn_cooldown = random.randint(200, 400) # 增加了生成间隔
else:
self.zombie_spawn_cooldown -= 1
# 随机生成阳光
if random.random() < 0.005: # 0.5%的几率每帧增加阳光
self.add_sun()
def draw(self, surface):
# 绘制背景
surface.fill(BLACK)
# 绘制草坪网格
for row in range(GRID_ROWS):
for col in range(GRID_COLS):
rect = pygame.Rect(
GRID_OFFSET_X + col * GRID_SIZE,
GRID_OFFSET_Y + row * GRID_SIZE,
GRID_SIZE,
GRID_SIZE
)
pygame.draw.rect(surface, (0, 100, 0) if (row + col) % 2 == 0 else (0, 120, 0), rect)
pygame.draw.rect(surface, (50, 50, 50), rect, 1)
# 绘制植物
for plant in self.plants:
plant.draw(surface)
# 绘制豌豆
for pea in self.peas:
pea.draw(surface)
# 绘制阳光
for sun in self.suns:
sun.draw(surface)
# 绘制僵尸
for zombie in self.zombies:
zombie.draw(surface)
# 绘制阳光值
sun_text = self.font.render(f"阳光: {self.sun}", True, WHITE)
surface.blit(sun_text, (20, SCREEN_HEIGHT - 50))
# 绘制植物卡片
for card in self.plant_cards:
selected = (self.selected_plant == card.plant_type)
card.draw(surface, self.sun, selected)
# 如果游戏结束,显示游戏结束文字
if self.game_over:
game_over_text = self.font.render("游戏结束! 按R键重新开始", True, RED)
surface.blit(game_over_text, (SCREEN_WIDTH//2 - 180, SCREEN_HEIGHT//2))
def handle_click(self, pos):
if self.game_over:
return
x, y = pos
# 检查是否点击了阳光
for sun in self.suns[:]:
if ((sun.x - x)**2 + (sun.y - y)**2) <= 400: # 20px半径内
self.sun += 25
sun.collected = True
return
# 检查是否点击了植物卡片
for card in self.plant_cards:
if card.is_clicked(pos) and card.is_ready(self.sun):
self.selected_plant = card.plant_type
card.cooldown = card.cooldown_max
self.sun -= card.cost
return
# 检查是否点击了草坪网格
if (GRID_OFFSET_X <= x <= GRID_OFFSET_X + GRID_COLS * GRID_SIZE and
GRID_OFFSET_Y <= y <= GRID_OFFSET_Y + GRID_ROWS * GRID_SIZE):
col = (x - GRID_OFFSET_X) // GRID_SIZE
row = (y - GRID_OFFSET_Y) // GRID_SIZE
if self.selected_plant:
if self.add_plant(row, col, self.selected_plant):
self.selected_plant = None
def reset(self):
self.__init__()
主游戏循环
def main():
game = Game()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
game.handle_click(event.pos)
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r and game.game_over:
game.reset()
game.update()
game.draw(screen)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
sys.exit()
if name == "main":
main()


浙公网安备 33010602011771号