import pygame
import sys
import random
import time
# 初始化Pygame
pygame.init()
# 游戏窗口尺寸
SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
# 设置标题
pygame.display.set_caption("植物大战僵尸")
# 加载图像
grass_img = pygame.image.load("grass.png").convert()
plant_img = pygame.image.load("plant.png").convert_alpha()
zombie_img = pygame.image.load("zombie.png").convert_alpha()
bullet_img = pygame.image.load("bullet.png").convert_alpha()
GRID_SIZE = 100
occupied_positions = set()
# 定义子弹类
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, speed=3):
super().__init__()
self.image = bullet_img
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.speed = speed
def update(self):
self.rect.x += self.speed # 子弹向右移动
if self.rect.right > SCREEN_WIDTH: # 如果子弹离开屏幕右侧,则销毁子弹
self.kill()
# 定义植物类
class Plant(pygame.sprite.Sprite):
def __init__(self, x, y, health=100, attack=1, shoot_interval=600):
super().__init__()
self.image = plant_img
self.rect = self.image.get_rect()
self.rect.topleft = (x, y)
self.health = health
self.attack = attack
self.shoot_interval = shoot_interval
self.last_shot = pygame.time.get_ticks()
def update(self):
now = pygame.time.get_ticks()
if now - self.last_shot > self.shoot_interval:
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
self.last_shot = now
if self.health <= 0:
self.kill()
# 定义僵尸类
class Zombie(pygame.sprite.Sprite):
def __init__(self, x, y, health=100, move_interval=60):
super().__init__()
self.image = zombie_img
self.rect = self.image.get_rect()
self.rect.topleft = (x, y)
self.health = health
self.move_interval = move_interval
self.last_move = pygame.time.get_ticks()
def update(self):
now = pygame.time.get_ticks()
if now - self.last_move >= self.move_interval:
self.rect.x -= 1 # 移动僵尸
self.last_move = now
if self.health <= 0:
self.kill()
# 定义波次系统类
class WaveSystem:
def __init__(self, wave_count=5):
self.wave_count = wave_count
self.current_wave = 1
self.zombies_in_wave = []
self.spawn_time = pygame.time.get_ticks()
self.spawn_delay = 1000 # 以毫秒为单位,即1秒
self.num_zombies_to_spawn = self.current_wave * 3 # 每波次的僵尸数量
def spawn_zombies(self, count=5):
current_time = pygame.time.get_ticks()
if current_time - self.spawn_time > self.spawn_delay:
self.spawn_time = current_time
remaining_zombies = self.num_zombies_to_spawn - len(self.zombies_in_wave)
for _ in range(min(count, remaining_zombies)):
# 生成僵尸的位置应该在屏幕宽度的右侧,并且Y坐标应该考虑网格大小
zombie = Zombie(SCREEN_WIDTH, random.randint(0, (SCREEN_HEIGHT - GRID_SIZE) // GRID_SIZE) * GRID_SIZE)
all_sprites.add(zombie)
zombies.add(zombie)
self.zombies_in_wave.append(zombie)
print(f"Spawned zombie at ({zombie.rect.x}, {zombie.rect.y})")
def next_wave(self):
# 检查当前波次的僵尸是否全部被消灭
if not self.zombies_in_wave:
print(f"Current wave: {self.current_wave}, zombies in wave: {len(self.zombies_in_wave)}")
self.current_wave += 2
if self.current_wave <= self.wave_count:
# 如果还有后续波次,则重置相关状态并开始新一波次
self.num_zombies_to_spawn = self.current_wave * 2 # 增加僵尸数量
self.spawn_time = pygame.time.get_ticks() # 重置生成计时器
self.zombies_in_wave = [] # 清空当前波次的僵尸列表
try:
self.spawn_zombies() # 开始生成新一波次的僵尸
except Exception as e:
print(f"Error while spawning zombies in next_wave: {e}")
raise
return True
else:
# 如果已经是最后一波,并且所有僵尸都被消灭,则游戏结束
print("游戏结束!")
return False
return True
# 其他方法...
# 其他方法...
# 创建 WaveSystem 实例
wave_system = WaveSystem(wave_count=5) # 例如,设置总共5波
# 创建精灵组
all_sprites = pygame.sprite.Group()
plants = pygame.sprite.Group()
zombies = pygame.sprite.Group()
bullets = pygame.sprite.Group()
# 游戏主循环
running = True
clock = pygame.time.Clock()
# 设置定时器
SPAWN_ZOMBIE_EVENT = pygame.USEREVENT + 1
pygame.time.set_timer(SPAWN_ZOMBIE_EVENT, 1000) # 每1000毫秒触发一次
while running:
clock.tick(50) # 控制游戏帧率为50FPS
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
# 用户点击鼠标时种植植物
mouse_pos = pygame.mouse.get_pos()
# 将鼠标点击位置映射到最近的网格点
grid_x = GRID_SIZE * (mouse_pos[0] // GRID_SIZE)
grid_y = GRID_SIZE * (mouse_pos[1] // GRID_SIZE)
# 检查该位置是否已经被占用
if (grid_x, grid_y) not in occupied_positions:
plant = Plant(grid_x, grid_y)
all_sprites.add(plant)
plants.add(plant)
occupied_positions.add((grid_x, grid_y))
else:
print("该位置已有植物,请选择其他位置!")
elif event.type == SPAWN_ZOMBIE_EVENT:
# 当定时器触发时生成僵尸
remaining_zombies = wave_system.num_zombies_to_spawn - len(wave_system.zombies_in_wave)
if remaining_zombies > 0:
wave_system.spawn_zombies(min(remaining_zombies, 1)) # 每次只生成一个僵尸
print(f"Remaining zombies to spawn: {remaining_zombies}")
# 检查是否进入下一波次
# if not wave_system.next_wave():
# print("Wave system returned False, setting running to False.")
# running = False
# 子弹与僵尸的碰撞处理
hits = pygame.sprite.groupcollide(bullets, zombies, True, False)
for bullet in hits:
for zombie in hits[bullet]:
zombie.health -= plant.attack
if zombie.health <= 0:
zombie.kill()
# 确保从 zombies_in_wave 列表中移除
if zombie in wave_system.zombies_in_wave:
wave_system.zombies_in_wave.remove(zombie)
# 检测僵尸与植物的碰撞
hits = pygame.sprite.groupcollide(zombies, plants, False, False)
for zombie in hits:
for plant in hits[zombie]:
plant.health -= 1 # 减少植物的生命值
if plant.health <= 0:
plant.kill() # 如果植物的生命值小于等于0,则移除植物
# 检查是否有僵尸被消灭,并尝试生成新的僵尸
for zombie in zombies.sprites():
if zombie.health <= 0:
wave_system.spawn_zombies(1) # 每消灭一个僵尸生成一个新的
# 检查是否有僵尸达到屏幕左侧
for zombie in zombies.sprites():
if zombie.rect.left < 0:
print("游戏失败!僵尸到达了屏幕左侧。")
running = False
# 更新精灵
all_sprites.update()
# 绘制背景
screen.fill((0, 0, 0))
screen.blit(grass_img, (0, 0))
# 绘制所有精灵
all_sprites.draw(screen)
# 更新屏幕
pygame.display.flip()
# 退出Pygame
pygame.quit()
sys.exit()
-
图片资源推荐网站
-
站酷ZCOOL(站酷网):www.zcool.com.cn
-
游侠网:3g.ali213.net
-
六图网(南通大牛文化传播有限公司):www.16pic.com