Python 植物大战僵尸

server/2024/9/20 1:21:49/ 标签: python

文章目录

  • 效果图
  • 项目结构
  • 实现思路
  • 源代码

效果图

请添加图片描述

项目结构

在这里插入图片描述

实现思路

下面是代码的实现思路:

  1. 导入必要的库和模块:首先,我们导入了Python的ostime库以及pygame库,还有植物大战僵尸游戏中用到的各个植物和僵尸的类。

  2. 初始化游戏和加载资源:接下来,我们初始化了Pygame库,并设置了游戏的背景尺寸。然后,我们加载了游戏所需的各种图像资源,包括背景、植物、僵尸等。

  3. 定义游戏元素和变量:我们定义了几个全局变量,包括阳光值、植物组、子弹组、僵尸组和阳光组。还定义了一些特殊事件,用于在游戏中生成新的植物、子弹、僵尸和阳光等。

  4. 编写游戏主循环:游戏的主循环在main()函数中。在主循环中,我们首先更新了植物、子弹和僵尸的位置和状态,然后在屏幕上绘制了这些元素。接下来,我们响应了用户的鼠标和键盘事件,包括选择植物、放置植物、收集阳光等。最后,我们更新了游戏界面并检查了游戏是否结束。

  5. 处理游戏事件:在主循环中,我们使用pygame.event.get()函数获取当前的游戏事件,并根据事件类型进行相应的处理。例如,当用户点击鼠标时,我们会判断用户是否点击了植物种子的图标,如果是,则将选择的植物类型设置为相应的值;如果用户点击了游戏区域,则根据选择的植物类型放置植物。

  6. 更新游戏状态和界面:在主循环中,我们还更新了游戏的状态,如减少阳光值、增加僵尸数量等。同时,我们也更新了游戏界面,如重新绘制阳光值、植物、僵尸等。

  7. 检查游戏结束条件:在主循环中,我们还检查了游戏是否结束。如果僵尸到达了终点,则游戏失败;如果僵尸数量大于一定值,则游戏胜利。

  8. 启动游戏:最后,我们在if __name__ == '__main__':代码块中调用了main()函数,启动游戏。

玩家可以选择不同的植物来抵御僵尸的进攻,并收集阳光来购买更多的植物。游戏通过不断生成新的僵尸和植物,以及响应用户的操作,来保持游戏的进行,直到游戏结束。

源代码

完整代码地址:https://gitcode.com/stormsha1/games/overview

pvz/main.py

python">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

请添加图片描述


http://www.ppmy.cn/server/31216.html

相关文章

UNIAPP小程序从入门到精通

第一章> 1、如何创建项目 2、项目的基本结构 3、页面组成&#xff08;wxss可以不用&#xff09; 4、组件的使用 5、协同开发与发布 第二章> 6、WXML页面结构渲染 7、style样式美化 8、a…

富格林:有效控制暗箱阻挠被骗

富格林悉知&#xff0c;当前现货黄金的行情波动较为激烈&#xff0c;对于我们投资者来说意味着投资盈利的机会多了&#xff0c;但同时投资暗箱风险亦随之而来。如果我们面对暗箱风险没有做好半点准备的话&#xff0c;可能会遭遇巨大损失甚至无法阻挠被骗。那么我们该如何阻挠被…

ASV1000视频监控平台:通过SDK接入海康网络摄像机IPC

目录 一、为何要通过SDK接入海康网络摄像机 &#xff08;一&#xff09;海康网络摄像机的SDK的功能 1、视频采集和显示 2、视频存储 3、视频回放 4、报警事件处理 5、PTZ控制 6、自定义设置 7、扩展功能 &#xff08;二&#xff09;通过SDK接入的好处&#xff08;相对…

【ZYNQ】Zynq 开发流程

Zynq 芯片架构由嵌入式处理器&#xff08;Processing System, PS&#xff09;与可编程逻辑&#xff08;Programmable Logic, PL&#xff09;&#xff0c;以及 PS 与 PL 之间的互联总线组成。本文主要介绍 Xilinx Zynq 芯片开发所使用的软件&#xff0c;包括 Vivado IDE 与 Xili…

菜鸡学习netty源码(三)—— Reactor 模型

1.概述 我们先进行理解一下Reactor模型&#xff0c;知道什么是Reactor模型&#xff0c;它有什么特别之处。我们先来简单介绍一下这个Reactor模型。 Reactor模型的核心思想&#xff1a; 就是将所关注的I/O事件进行注册到一个多路复用器上&#xff0c;一旦有I/O事件的发生&#…

如何让 PDF 书签从杂乱无序整洁到明丽清新

1、拉取书签&#xff08;详细步骤看文末扩展阅读&#xff09; 原状态 —— 杂乱无序 自动整理后的状态 —— 错落有致&#xff0c;但摩肩接踵 2、开始整理 全选自动整理后的书签&#xff0c;剪切 访问中英混排排版优化 - 油条工具箱 https://utils.fun/cn-en 1 粘贴 → 2 …

【代码随想录】day48

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、198打家劫舍二、213打家劫舍II三、337打家劫舍III 一、198打家劫舍 class Solution { public:int rob(vector<int>& nums) {vector<int> dp(n…

Linux编辑器——vim的基础使用

文章目录 1.vim的基本概念2.vim的基本操作3.vim命令模式命令集3.1移动光标3.2删除文字3.3复制3.4替换3.5撤销3.6更改3.7跳到指定的行 1.vim的基本概念 本文将介绍vim的三种模式&#xff0c;分别位&#xff1a;命令模式、插入模式、低行模式。他们的功能区分如下&#xff1a; 正…

PaLmTac嵌入软体手手掌的视触觉传感器

触觉是感知和操作之间的桥梁。触觉信息对于手部行为反馈和规划具有重要意义。软体手的柔性特性在人机交互、生物医学设备和假肢等方面具有潜在应用的优势。本文提出了一种名为 PaLmTac的嵌入软体手手掌的视触觉传感器&#xff08;vision-based tactile sensor, VBTS&#xff09…

基于小程序实现的投票评选系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

ArrayList还是LinkedList?

引言 集合作为一种存储数据的容器&#xff0c;是我们日常开发中使用最频繁的对象类型之一。JDK为开发者提供了一系列的集合类型&#xff0c;这些集合类型使用不同的数据结构来实现。因此&#xff0c;不同的集合类型&#xff0c;使用场景也不同。 很多同学在面试的时候&#x…

ElasticSearch教程入门到精通——第一部分(基于ELK技术栈elasticsearch 8.x新特性)

ElasticSearch教程入门到精通——第一部分&#xff08;基于ELK技术栈elasticsearch 8.x新特性&#xff09; 1. ElasticSearch安装&#xff08;略&#xff09;2. ElasticSearch基础功能2.1 索引操作2.1.1 创建索引2.1.2 Head 索引2.1.3 查询索引2.1.3.1 查询单独索引2.1.3.2 查询…

XYCTF2024 RE ez unity 复现

dll依然有加壳 但是这次global-metadata.dat也加密了&#xff0c;原工具没办法用了&#xff0c;不过依然是可以修复的 a. 法一&#xff1a;frida-il2cpp-bridge 可以用frida-il2cpp-bridge GitHub - vfsfitvnm/frida-il2cpp-bridge: A Frida module to dump, trace or hijac…

全栈开发之路——前端篇(4)watch监视、数据绑定和计算属性

全栈开发一条龙——前端篇 第一篇&#xff1a;框架确定、ide设置与项目创建 第二篇&#xff1a;介绍项目文件意义、组件结构与导入以及setup的引入。 第三篇&#xff1a;setup语法&#xff0c;设置响应式数据。 辅助文档&#xff1a;HTML标签大全&#xff08;实时更新&#xff…

Jenkins(超详细的Docker安装Jenkins教程!!!)

Jenkins Jenkins&#xff0c;原名 Hudson&#xff0c;2011 年改为现在的名字。它是一个开源的实现持续集成的软件工具。 官方网站&#xff1a;https://www.jenkins.io/ 中文文档&#xff1a;https://www.jenkins.io/zh/ 为什么需要Jenkins&#xff1f; 我们以前写完代码&a…

设计模式之业务代表模式

在编程江湖的风雨中漂泊多年&#xff0c;每当我遇到那些错综复杂的业务逻辑和系统交互&#xff0c;总有一个模式像一位忠诚的骑士&#xff0c;默默守护着我的代码城堡&#xff0c;那就是——业务代表模式&#xff08;Business Delegate Pattern&#xff09;。它不是最耀眼的明星…

全面学习SpringCloud框架指南

要深入学习Spring Cloud框架&#xff0c;你需要系统地掌握其核心组件和概念&#xff0c;并了解如何在实际项目中应用这些知识。以下是一些关键的学习点和相应的学习内容&#xff1a; 一共分为10个模块包括&#xff1a; 1、微服务架构基础&#xff1a; 理解微服务架构的概念和…

STM32H745BIT6上的ARM Cortex-M7和Cortex-M4核心共享SRAM4中的数据的方法

目录 1.Cortex-M7 Core (主核心) 2.Cortex-M4 Core (从核心) 3.具体代码示例 &#xff08;1&#xff09;Cortex-M7 Core (主核心) &#xff08;2&#xff09;Cortex-M4 Core (从核心) &#xff08;3&#xff09;总结 4.额外的知识点&#xff1a;原子操作 &#xff08;1…

【研发管理】产品经理知识体系-产品创新流程

导读&#xff1a;产品创新流程是一个系统性的过程&#xff0c;旨在通过创造和引入新的产品或改进现有产品来满足市场需求、解决用户问题或实现竞争优势。 目录 1、产品创新引论 2、决策基本框架 3、模糊前端 4、产品创新流程模型概论 5、门径管理流程 6、并行工程和集成产…

在Ubuntu上怎么查看安装了哪些包?

2024年5月3日&#xff0c;周五晚上 在Ubuntu上&#xff0c;你可以使用以下命令来查看系统中已安装的包&#xff1a; 使用dpkg命令&#xff1a;dpkg --list这个命令将列出系统中所有已安装的软件包&#xff0c;包括名称、版本号和描述等信息。你可以使用 grep 命令来过滤结果&a…