Python 植物大战僵尸
文章目录
- 效果图
- 项目结构
- 实现思路
- 源代码
效果图

项目结构

实现思路
下面是代码的实现思路:
-
导入必要的库和模块:首先,我们导入了Python的
os、time库以及pygame库,还有植物大战僵尸游戏中用到的各个植物和僵尸的类。 -
初始化游戏和加载资源:接下来,我们初始化了Pygame库,并设置了游戏的背景尺寸。然后,我们加载了游戏所需的各种图像资源,包括背景、植物、僵尸等。
-
定义游戏元素和变量:我们定义了几个全局变量,包括阳光值、植物组、子弹组、僵尸组和阳光组。还定义了一些特殊事件,用于在游戏中生成新的植物、子弹、僵尸和阳光等。
-
编写游戏主循环:游戏的主循环在
main()函数中。在主循环中,我们首先更新了植物、子弹和僵尸的位置和状态,然后在屏幕上绘制了这些元素。接下来,我们响应了用户的鼠标和键盘事件,包括选择植物、放置植物、收集阳光等。最后,我们更新了游戏界面并检查了游戏是否结束。 -
处理游戏事件:在主循环中,我们使用
pygame.event.get()函数获取当前的游戏事件,并根据事件类型进行相应的处理。例如,当用户点击鼠标时,我们会判断用户是否点击了植物种子的图标,如果是,则将选择的植物类型设置为相应的值;如果用户点击了游戏区域,则根据选择的植物类型放置植物。 -
更新游戏状态和界面:在主循环中,我们还更新了游戏的状态,如减少阳光值、增加僵尸数量等。同时,我们也更新了游戏界面,如重新绘制阳光值、植物、僵尸等。
-
检查游戏结束条件:在主循环中,我们还检查了游戏是否结束。如果僵尸到达了终点,则游戏失败;如果僵尸数量大于一定值,则游戏胜利。
-
启动游戏:最后,我们在
if __name__ == '__main__':代码块中调用了main()函数,启动游戏。
玩家可以选择不同的植物来抵御僵尸的进攻,并收集阳光来购买更多的植物。游戏通过不断生成新的僵尸和植物,以及响应用户的操作,来保持游戏的进行,直到游戏结束。
源代码
完整代码地址:https://gitcode.com/stormsha1/games/overview
pvz/main.py
import os
import time
import pygame
from pvz.plant.Peashooter import Peashooter
from pvz.plant.SunFlower import SunFlower
from pvz.plant.WallNut import WallNut
from pvz.plant.Sun import Sun
from pvz.plant.Sun2 import Sun2
from pvz.plant.JXC import JXC
from pvz.plant.Bullet import Bullet
from pvz.plant.BulletJXC import BulletJXC
from pvz.zombie.Zombie import Zombie
from pvz.zombie.ZombieLz import ZombieLz# 初始化pygame库
pygame.init()# 设置游戏背景尺寸,所有的资源图片都是基于这个尺寸制作的,不建议修改
background_size = (820, 560)# 创建游戏窗口并设置标题
screen = pygame.display.set_mode(background_size)
pygame.display.set_caption("植物大战僵尸")# 获取当前工作目录
base_path = os.getcwd()# 加载背景图片
bg_img_obj = pygame.image.load(os.path.join(base_path, 'images/a3.png')).convert_alpha()# 加载植物图片
sunFlowerImg = pygame.image.load(os.path.join(base_path, 'images/SunFlower/SunFlower_00.png')).convert_alpha()
wallNutImg = pygame.image.load(os.path.join(base_path, 'images/WallNut/wall_nut_00.png')).convert_alpha()
peaShooterImg = pygame.image.load(os.path.join(base_path, 'images/Peashooter/Peashooter00.png')).convert_alpha()
jxcImg = pygame.image.load(os.path.join(base_path, 'images/jxc/JXC00.png')).convert_alpha()# 加载阳光储蓄罐和种子图片
sun_back_img = pygame.image.load(os.path.join(base_path, 'images/SeedBank01.png')).convert_alpha()
sunflower_seed = pygame.image.load(os.path.join(base_path, 'images/SunFlower_kp.png'))
wall_nut_seed = pygame.image.load(os.path.join(base_path, 'images/Wallnut_kp.png'))
peashooter_seed = pygame.image.load(os.path.join(base_path, 'images/Peashooter_kp.png'))
jxc_seed = pygame.image.load(os.path.join(base_path, 'images/jxc_kp.png'))# 初始化阳光值为100
text = "1000"# 设置阳光值字体和颜色
sun_font = pygame.font.SysFont("黑体", 25)
sun_num_surface = sun_font.render(str(text), True, (0, 0, 0))# 创建植物组、子弹组、僵尸组和阳光组
spriteGroup = pygame.sprite.Group()
bulletGroup = pygame.sprite.Group()
zombieGroup = pygame.sprite.Group()
sun_sprite = pygame.sprite.Group()# 定义游戏时钟和特殊事件
clock = pygame.time.Clock()
GEN_SUN_EVENT = pygame.USEREVENT + 1 # 生成阳光事件
pygame.time.set_timer(GEN_SUN_EVENT, 2000) # 每2秒生成一次阳光
GEN_BULLET_EVENT = pygame.USEREVENT + 2 # 生成子弹事件
pygame.time.set_timer(GEN_BULLET_EVENT, 2000) # 每2秒生成一次子弹
GEN_ZOMBIE_EVENT = pygame.USEREVENT + 3 # 生成僵尸事件
pygame.time.set_timer(GEN_ZOMBIE_EVENT, 10000) # 每10秒生成一次僵尸
GEN_SUN2_EVENT = pygame.USEREVENT + 4 # 生成双倍阳光事件
pygame.time.set_timer(GEN_SUN2_EVENT, 20000) # 每20秒生成一次双倍阳光# 初始化选择的植物类型和僵尸数量
choose = 0
zombie_num = 0def main():"""游戏主函数,包含游戏主循环"""global zombie_num # 僵尸数量全局变量global choose # 选择的植物类型全局变量global text # 阳光值全局变量global sun_num_surface # 阳光值显示表面全局变量running = True # 游戏是否运行标志index = 0 # 用于植物、子弹和僵尸的更新和绘制的索引while running:# 控制游戏帧率clock.tick(20)# 检查子弹和僵尸的碰撞,如果碰撞则减少僵尸的能量并移除子弹for bullet in bulletGroup:for zombie in zombieGroup:if pygame.sprite.collide_mask(bullet, zombie):if isinstance(bullet, BulletJXC): # 如果是坚果的子弹,则减少2点能量zombie.energy -= 2bulletGroup.remove(bullet)else: # 否则减少1点能量zombie.energy -= 1bulletGroup.remove(bullet)# 检查植物和僵尸的碰撞,如果碰撞则设置僵尸的GO标志为True,并将僵尸添加到植物的zombies列表中for sprite in spriteGroup:for zombie in zombieGroup:if pygame.sprite.collide_mask(sprite, zombie):zombie.GO = Truesprite.zombies.add(zombie)# 如果植物是坚果,则检查僵尸是否在攻击范围内,如果是则设置植物的攻击标志为True,并生成子弹if isinstance(sprite, JXC):if abs(zombie.rect.top - sprite.rect[1]) <= 40 and zombie.rect.left < 760:sprite.attack = Trueif sprite.att == 11:bullet_jxc = BulletJXC(sprite.rect, background_size, zombie.rect[0])bulletGroup.add(bullet_jxc)break# 在屏幕上绘制背景、阳光储蓄罐、阳光值和种子图片screen.blit(bg_img_obj, (0, 0))screen.blit(sun_back_img, (20, 0.5))screen.blit(sun_num_surface, (35, 50))screen.blit(sunflower_seed, (80, 5))screen.blit(peashooter_seed, (121, 5))screen.blit(wall_nut_seed, (162, 5))screen.blit(jxc_seed, (203, 5))# 更新和绘制植物、子弹、僵尸和阳光spriteGroup.update(index)spriteGroup.draw(screen)bulletGroup.update(index)bulletGroup.draw(screen)zombieGroup.update(index)zombieGroup.draw(screen)sun_sprite.update(index)sun_sprite.draw(screen)# 获取鼠标位置,并在鼠标位置上绘制选择的植物预览图(x, y) = pygame.mouse.get_pos()if choose == 1:screen.blit(sunFlowerImg, (x - sunFlowerImg.get_rect().width // 2, y - sunFlowerImg.get_rect().height // 2))if choose == 2:screen.blit(peaShooterImg,(x - peaShooterImg.get_rect().width // 2, y - peaShooterImg.get_rect().height // 2))if choose == 3:screen.blit(wallNutImg, (x - wallNutImg.get_rect().width // 2, y - wallNutImg.get_rect().height // 2))if choose == 4:screen.blit(jxcImg, (x - jxcImg.get_rect().width // 2, y - jxcImg.get_rect().height // 2))# 增加索引值index += 1# 处理pygame事件for event in pygame.event.get():# 处理生成双倍阳光事件if event.type == GEN_SUN2_EVENT:sun2 = Sun2()sun_sprite.add(sun2)# 处理生成僵尸事件if event.type == GEN_ZOMBIE_EVENT:zombie_num += 1zombie = Zombie()zombie_lz = ZombieLz()if 0 < zombie_num <= 15:zombieGroup.add(zombie)if zombie_num > 7:zombieGroup.add(zombie_lz)# 处理生成阳光事件if event.type == GEN_SUN_EVENT:for sprite in spriteGroup:if isinstance(sprite, SunFlower):now = time.time()if now - sprite.last_time >= 10: # 如果距离上次生成阳光的时间大于等于10秒,则生成阳光sun = Sun(sprite.rect)sun_sprite.add(sun)sprite.last_time = now# 处理生成子弹事件if event.type == GEN_BULLET_EVENT:for sprite in spriteGroup:for zombie in zombieGroup:if isinstance(sprite, Peashooter) \and 0 < sprite.rect[1] - zombie.rect[1] < 50 \and zombie.rect[0] < 760:bullet = Bullet(sprite.rect, background_size)bulletGroup.add(bullet)break# 处理退出游戏事件if event.type == pygame.QUIT:running = False# 处理鼠标点击事件if event.type == pygame.MOUSEBUTTONDOWN:pressed_key = pygame.mouse.get_pressed()if pressed_key[0]:pos = pygame.mouse.get_pos()x, y = pos# 如果点击了种子按钮,则设置选择的植物类型if 80 <= x < 121 and 5 <= y <= 63 and int(text) >= 50:choose = 1elif 121 <= x < 162 and 5 <= y <= 63 and int(text) >= 100:choose = 2elif 162 <= x < 203 and 5 <= y <= 63 and int(text) >= 50:choose = 3elif 203 <= x < 244 and 5 <= y <= 63 and int(text) >= 100:choose = 4# 如果点击了游戏区域,则根据选择的植物类型放置植物elif 36 < x < 800 and 70 < y < 550:if choose == 1:true_x = x // 90 * 85 + 35 # 计算植物的左上角坐标true_y = y // 100 * 95 - 15can_hold = True # 是否可以放置植物标志for sprite in spriteGroup:if sprite.rect.left == true_x and sprite.rect.top == true_y:can_hold = Falsebreakif not can_hold or true_y < 25:breaksunflower = SunFlower(time.time(), (true_x, true_y)) # 创建向日葵实例spriteGroup.add(sunflower) # 将向日葵添加到植物组中choose = 0 # 重置选择的植物类型text = int(text) # 将阳光值转换为整数text -= 50 # 减少50阳光my_font = pygame.font.SysFont("黑体", 25) # 设置字体sun_num_surface = my_font.render(str(text), True, (0, 0, 0)) # 更新阳光值显示表面if choose == 2:true_x = x // 90 * 85 + 32true_y = y // 100 * 95 - 18can_hold = Truefor sprite in spriteGroup:if sprite.rect.left == true_x and sprite.rect.top == true_y:can_hold = Falsebreakif not can_hold or true_y < 25:breakpeashooter = Peashooter((true_x, true_y)) # 创建豌豆射手实例spriteGroup.add(peashooter) # 将豌豆射手添加到植物组中choose = 0text = int(text)text -= 100 # 减少100阳光my_font = pygame.font.SysFont("黑体", 25)sun_num_surface = my_font.render(str(text), True, (0, 0, 0))if choose == 3:true_x = x // 90 * 85 + 35true_y = y // 100 * 95 - 15can_hold = Truefor sprite in spriteGroup:if sprite.rect.left == true_x and sprite.rect.top == true_y:can_hold = Falsebreakif not can_hold or true_y < 25:breakwall_nut = WallNut((true_x, true_y)) # 创建坚果实例spriteGroup.add(wall_nut) # 将坚果添加到植物组中choose = 0text = int(text)text -= 50 # 减少50阳光my_font = pygame.font.SysFont("黑体", 25)sun_num_surface = my_font.render(str(text), True, (0, 0, 0))if choose == 4:true_x = x // 90 * 85 + 22true_y = y // 100 * 95 - 35can_hold = Truefor sprite in spriteGroup:if sprite.rect.left == true_x and sprite.rect.top == true_y:can_hold = Falsebreakif not can_hold or true_y < 25:breakjxc = JXC((true_x, true_y)) # 创建坚果墙实例spriteGroup.add(jxc) # 将坚果墙添加到植物组中choose = 0text = int(text)text -= 100 # 减少100阳光my_font = pygame.font.SysFont("黑体", 25)sun_num_surface = my_font.render(str(text), True, (0, 0, 0))# 如果点击了阳光,则收集阳光并更新阳光值显示表面for sun in sun_sprite:if sun.rect.collidepoint(pos):sun_sprite.remove(sun)text = str(int(text) + 25)sun_font = pygame.font.SysFont("黑体", 25)sun_num_surface = sun_font.render(str(text), True, (0, 0, 0))# 检查僵尸是否到达终点或游戏是否胜利for zombie in zombieGroup:if zombie.rect.left == -120: # 如果僵尸到达终点,则游戏失败print("你的脑子被僵尸吃了")running = Falseif zombie_num > 20: # 如果僵尸数量大于20,则游戏胜利print("胜利")running = False# 更新游戏界面pygame.display.update()if __name__ == '__main__':main()
完整代码地址:https://gitcode.com/stormsha1/games/overview

相关文章:
Python 植物大战僵尸
文章目录 效果图项目结构实现思路源代码 效果图 项目结构 实现思路 下面是代码的实现思路: 导入必要的库和模块:首先,我们导入了Python的os、time库以及pygame库,还有植物大战僵尸游戏中用到的各个植物和僵尸的类。 初始化游戏和…...
SpringBoot:实战项目TLIAS智能学习辅助系统1.1
SpringBootWeb项目 TILAS智能学习辅助系统 需求 部门管理 查询部门列表 删除部门 新增部门 修改部门 员工管理 查询员工列表(分页) 删除员工 新增员工 修改员工 准备工作 导入依赖 web(2.7.6) mybatis mysql驱动 lombok 准备好包结构 Controller->Servi…...
ubuntu-meta-22.04桌面版+ros2-humble 镜像
ubuntu-meta-22.04桌面版ros2-humble 镜像 下载地址: 链接:https://pan.baidu.com/s/1PSBe4EqWch44OQUlkCCEig?pwdknty 提取码:knty 镜像文件较大,分成了两个压缩包,下载后直接解压ubuntu22.04-desk-meta-ros2-arm (…...
『大模型笔记』Code Example: Function Calling with ChatGPT
Code Example: Function Calling with ChatGPT 文章目录 一. Code Example: Function Calling with ChatGPT二. 参考文献一. Code Example: Function Calling with ChatGPT from openai import OpenAI from dotenv import load_dotenv import json# --------------------------…...
【智能算法应用】混合粒子群算法求解CVRP问题
目录 1.算法原理2.数学模型3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】粒子群算法(PSO)原理及实现 经典PSO算法用于连续空间优化问题,VRP问题为离散组合优化问题,涉及如何有效地分配一组车辆去访问多个客户点&…...
Python项目开发实战:飞机大战游戏(案例教程)
一、引言 飞机大战游戏是一款经典的射击类游戏,玩家需要驾驶飞机在空中与敌人进行战斗,躲避敌人的攻击,同时发射子弹消灭敌人。本文将详细介绍如何使用Python及其相关库来开发一款简单的飞机大战游戏,包括游戏的设计思路、开发过…...
音频压缩的方法有哪些?3种简单的压缩工具分享
音频压缩的方法有哪些?音频压缩是处理音频文件时的一个重要步骤,旨在减小文件大小,同时尽量保持原始音频的质量。随着数字媒体的普及,音频文件的大小成为了一个重要的考虑因素。通过有效的音频压缩技术,我们能够在保持…...
阿里云CentOS7 打开/关闭防火墙 开放端口
#查看防火墙状态# systemctl status firewalld #关闭防火墙# systemctl stop firewalld #打开防火墙# systemctl start firewalld #添加开放2375端口# firewall-cmd --add-port2375/tcp --permanent #重载入添加的端口# firewall-cmd --reload #查询2375端口是否开启成…...
React 组件性能优化
React 组件性能优化的核心是减少渲染真实 DOM 节点的频率,减少 Virtual DOM 比对的频率。 1. 组件卸载前进行清理操作 window 注册的全局事件, 以及定时器 useEffect(()>{return ()>{// do somethingclearTimeout(tiemr)window.removeEventListener(xxx, c…...
jvm 马士兵 01 JVM简介,class文件结构
01.JVM是什么 JVM是一个跨平台的标准 JVM只识别class文件,符合JVM规范的class文件都可以被识别 u1 是一个字节 u2是两个字节...
PostgreSQL自带的命令行工具02- createdb
PostgreSQL自带的命令行工具02- createdb 基础信息 OS版本:Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本:16.2 pg软件目录:/home/pg16/soft pg数据目录:/home/pg16/data 端口:5777createdb 是 Postgr…...
软件设计师-重点的构造型设计模式
一、桥接模式(Bridge): 意图: 将抽象部分与其实现部分分离,使它们都可以独立地变化。 结构: 适用性: 不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是…...
Java面试问题及答案
Java面试问题及答案 以下是几个Java面试中可能会问到的问题及其答案。 1. 解释Java中的多态性是什么,以及它是如何工作的? 问题: 在Java中,多态性是指允许不同类的对象对同一消息做出响应的能力,即同一个接口可以被…...
STM32 01
1、编码环境 1.1 安装keil5 1.2 安装STM32CubeMX 使用STM32CubeMX可以通过界面的方式,快速生成工程文件 安装包可以从官网下载:https://www.st.com/zh/development-tools/stm32cubemx.html#overview 安装完要注意更新一下固件包的位置,因为…...
学习笔记:【QC】Android Q - phone 模块
一、phone init 流程图 二、phone MO 流程图 三、phone MT 流程图 四、Log分析(MO_qcril_hal_分析) 1、RILJ请求dial enqueue进队列,QCRIL-hal pop出来处理,最后还是调用qmi_client_send_msg_async发送给modem 11-07 17:29:23.598 2758 2758 D RILJ …...
webscoket+webrtc实现语音通话
1.项目方案 前端采用webrtc创建音频上下文,后创建音频源输入和音频处理器,连接音频输入与处理器,处理器再连接到音频输出(扬声器),再通过事件获取音频数据,把音频数据转换成字节数据通过webscok…...
PHP源码_众筹商城
众筹商城源码 众筹商品平台 商城加共识元富之路 网上商城众筹 前端是编译后的,后端PHP,带商城 运行截图 源码贡献 https://githubs.xyz/boot?app39 部分数据库表 CREATE TABLE ti_shopro_store (id int(11) NOT NULL AUTO_INCREMENT COMMENT ID,nam…...
智能小程序 Ray 开发——表单组件 Button 和 Checkbox 实操讲解
Button 多端按钮基础组件,可用于进行强交互的操作。 导入 import { Button } from ray-js/ray; 属性说明 属性类型默认值必填说明支持平台sizekeyof Sizedefault否按钮的大小涂鸦、微信typekeyof Typedefault否按钮的样式类型涂鸦、微信plainbooleanfalse否按钮…...
渗透之sql注入联合查询的注入
sql注入产生的原因: 由于程序过滤不严谨,导致用户有一些异常输入,最终触发数据库的查询。所以会出现sql注入这个问题。有些恶意的人就会利用这些信息导致数据库泄露。 注意:一般我们存在注入点我们会查询管理员的账号和密码&#…...
NLP transformers - 文本分类
Text classification 文章目录 Text classification加载 IMDb 数据集Preprocess 预处理EvaluateTrainInference 本文翻译自:Text classification https://huggingface.co/docs/transformers/tasks/sequence_classification notebook : https://colab.research.googl…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
