Python 植物大战僵尸

news2024/12/23 18:02:50

文章目录

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

效果图

请添加图片描述

项目结构

在这里插入图片描述

实现思路

下面是代码的实现思路:

  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

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 = 0


def 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 -= 2
                        bulletGroup.remove(bullet)
                    else:  # 否则减少1点能量
                        zombie.energy -= 1
                        bulletGroup.remove(bullet)

        # 检查植物和僵尸的碰撞,如果碰撞则设置僵尸的GO标志为True,并将僵尸添加到植物的zombies列表中
        for sprite in spriteGroup:
            for zombie in zombieGroup:
                if pygame.sprite.collide_mask(sprite, zombie):
                    zombie.GO = True
                    sprite.zombies.add(zombie)
                # 如果植物是坚果,则检查僵尸是否在攻击范围内,如果是则设置植物的攻击标志为True,并生成子弹
                if isinstance(sprite, JXC):
                    if abs(zombie.rect.top - sprite.rect[1]) <= 40 and zombie.rect.left < 760:
                        sprite.attack = True
                        if 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 += 1
                zombie = 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 = 1
                    elif 121 <= x < 162 and 5 <= y <= 63 and int(text) >= 100:
                        choose = 2
                    elif 162 <= x < 203 and 5 <= y <= 63 and int(text) >= 50:
                        choose = 3
                    elif 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 - 15
                            can_hold = True  # 是否可以放置植物标志
                            for sprite in spriteGroup:
                                if sprite.rect.left == true_x and sprite.rect.top == true_y:
                                    can_hold = False
                                    break
                            if not can_hold or true_y < 25:
                                break
                            sunflower = 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 + 32
                            true_y = y // 100 * 95 - 18
                            can_hold = True
                            for sprite in spriteGroup:
                                if sprite.rect.left == true_x and sprite.rect.top == true_y:
                                    can_hold = False
                                    break
                            if not can_hold or true_y < 25:
                                break
                            peashooter = Peashooter((true_x, true_y))  # 创建豌豆射手实例
                            spriteGroup.add(peashooter)  # 将豌豆射手添加到植物组中
                            choose = 0
                            text = 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 + 35
                            true_y = y // 100 * 95 - 15
                            can_hold = True
                            for sprite in spriteGroup:
                                if sprite.rect.left == true_x and sprite.rect.top == true_y:
                                    can_hold = False
                                    break
                            if not can_hold or true_y < 25:
                                break
                            wall_nut = WallNut((true_x, true_y))  # 创建坚果实例
                            spriteGroup.add(wall_nut)  # 将坚果添加到植物组中
                            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 == 4:
                            true_x = x // 90 * 85 + 22
                            true_y = y // 100 * 95 - 35
                            can_hold = True
                            for sprite in spriteGroup:
                                if sprite.rect.left == true_x and sprite.rect.top == true_y:
                                    can_hold = False
                                    break
                            if not can_hold or true_y < 25:
                                break
                            jxc = JXC((true_x, true_y))  # 创建坚果墙实例
                            spriteGroup.add(jxc)  # 将坚果墙添加到植物组中
                            choose = 0
                            text = 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 = False
                if zombie_num > 20:  # 如果僵尸数量大于20,则游戏胜利
                    print("胜利")
                    running = False

        # 更新游戏界面
        pygame.display.update()


if __name__ == '__main__':
    main()

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

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1641042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一机游领航旅游智慧化浪潮:借助前沿智能设备,革新旅游服务效率,构建高效便捷、生态友好的旅游服务新纪元,开启智慧旅游新时代

目录 一、引言 二、一机游的定义与特点 &#xff08;一&#xff09;一机游的定义 &#xff08;二&#xff09;一机游的特点 三、智能设备在旅游服务中的应用 &#xff08;一&#xff09;旅游前的信息查询与预订支付 &#xff08;二&#xff09;旅游中的导航导览与互动体…

【JVM】Java工具(Arthas,APM,Java Agent,JMX)

Java工具 常见的Java工具有以下几类&#xff1a; 1、诊断类工具&#xff0c;如Arthas、VisualVM等。 2、开发类工具&#xff0c;如Idea、Eclipse。 3、APM应用性能监测工具&#xff0c;如Skywalking、Zipkin等。 4、热部署工具&#xff0c;如Jrebel等。 Arthas中 Java Ag…

window 安装ai 基础环境(yolo8,训练推理等)

步骤: 1. python sdk 3.9以上 2. 显卡驱动 可以使用驱动精灵 直接安装N 卡推荐 3. 安装机器学习套件CUDA cuda 安装在PyTorch 需要根 PyTorch版本一致&#xff0c;我的 win-srv 最高支持 12.1 下载地址&#xff1a; https://developer.nvidia.com/cuda-toolkit-archive…

吴恩达2022机器学习专项课程(一)正则化(正则化成本函数正则化线性回归正则化逻辑回归)

目录 一.正则化1.1 正则化的好处1.2 正则化的实现方式 二.正则化改进线性回归的成本函数2.1 正则化后的成本函数的意义2.2 λ参数的作用2.3 不同λ对算法的影响2.4 为什么参数b没有正则化项 三.正则化线性回归的梯度下降3.1 为什么正则化可以在梯度下降迭代中减小w3.2 导数的计…

如何使用 GPT API 从 PDF 出版物导出研究图表?

原文地址&#xff1a;how-to-use-gpt-api-to-export-a-research-graph-from-pdf-publications 揭示内部结构——提取研究实体和关系 2024 年 2 月 6 日 介绍 研究图是研究对象的结构化表示&#xff0c;它捕获有关实体的信息以及研究人员、组织、出版物、资助和研究数据之间的关…

Java Jackson-jr 库使用介绍

介绍 Jackson-jr 是一个轻量级的Java JSON 处理库。这个库被设计用来替代 Jackson 的复杂性。对比 Jackson 的复杂 API&#xff0c;Jackson-jr 的启动速度更快&#xff0c;包大小更小。 虽然Jackson databind&#xff08;如ObjectMapper&#xff09;是通用数据绑定的良好选择…

Redis---------分布式锁Redisson

概述 Redisson入门 第一步&#xff1a;引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.6</version></dependency> 第二步&#xff1a;配置文件 import org.redisson…

django搭建一个AI博客进行YouTube视频自动生成文字博客

文章目录 一、生成Django框架二、项目代码&#xff08;前端&#xff09;1、编写前端代码&#xff08;正文界面&#xff09;1.1、生产html框架1.2、添加live preview扩展1.3、更改title元素中文本1.4、添加CDN&#xff08;CSS&#xff09;样式链接1.5、nav标签1.6、在body标签中…

全面了解俄罗斯的VK开户和Yandex投放及内容运营

俄罗斯的VKontakte&#xff08;简称VK&#xff09;和Yandex是两个重要的在线平台&#xff0c;对于希望在俄罗斯市场进行推广的企业来说&#xff0c;了解如何在这些平台上开户和投放广告以及内容运营是非常关键的。 俄罗斯vk广告如何开户&#xff1f; 通过上海上弦进行俄罗斯V…

ASP.NET网络在线考试系统

摘 要 随着计算机技术的发展和互联网时代的到来&#xff0c;人们已经进入了信息时代&#xff0c;也有人称为数字化时代。数在数字化的网络环境下&#xff0c;学生希望得到个性化的满足&#xff0c;根据自己的情况进行学习&#xff0c;同时也希望能够得到科学的评价&#xff0c…

(4)步态识别论文研读——增强时空显著性的跨视图步态识别

Enhanced Spatial-Temporal Salience for Cross-View Gait Recognition Enhanced Spatial-Temporal Salience for Cross-View Gait Recognition | IEEE Journals & Magazine | IEEE Xplore 摘要:步态识别可以单独或与其他生物特征相结合&#xff0c;用于个人识别和再识别…

242 基于matlab的3D路径规划

基于matlab的3D路径规划&#xff0c;蚁群算法&#xff08;ACO&#xff09;和天牛须&#xff08;BAS&#xff09;以及两种结合的三种优化方式&#xff0c;对3D路径规划的最短路径进行寻优。程序已调通&#xff0c;可直接运行。 242 3D路径规划 蚁群算法和天牛须 - 小红书 (xiaoh…

Redis---------实现更改数据业务,包括缓存更新,缓存穿透雪崩击穿的处理

三种更新策略 内存淘汰是Redis内存的自动操作&#xff0c;当内存快满了就会触发内存淘汰。超时剔除则是在存储Redis时加上其有限期(expire)&#xff0c;有限期一过就会自动删除掉。而主动更新则是自己编写代码去保持更新&#xff0c;所以接下来研究主动更新策略。 主动更新策略…

docker系列9:容器卷挂载(下)

传送门 docker系列1&#xff1a;docker安装 docker系列2&#xff1a;阿里云镜像加速器 docker系列3&#xff1a;docker镜像基本命令 docker系列4&#xff1a;docker容器基本命令 docker系列5&#xff1a;docker安装nginx docker系列6&#xff1a;docker安装redis docker系…

基于yolov8的苹果腐败检测系统,系统既支持图像检测,也支持视频和摄像实时检测(pytorch框架)【python源码+UI界面+功能源码详解】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于yolov8的苹果腐败检测系统&#xff0c;系统既支持图像检测&#xff0c;也支持视频和摄像实时检测_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov8的苹果腐败检测系统是在pytorc…

QT:label标签/进度条的使用

文章目录 设置不同格式的文本显示图片文本对齐/自动换行/缩进/边距LCDNumber倒计时 ProgressBar进度条 设置不同格式的文本 在文本格式中&#xff0c;存在富文本&#xff0c;makedown格式的文本&#xff0c;还有纯文本&#xff0c;下面就依据这三个进行举例 #include "w…

MySQL-SQL执行流程及原理

1、SQL执行流程 2、查询流程 查询缓存&#xff1a; MySQL服务器如果在查询缓存中存在该SQL语句&#xff0c;就直接将结果返回给客户端&#xff0c;没有就进入解析器解析阶段。&#xff08;MySQL 8.0 删除该功能&#xff09;解析器&#xff1a;在解析器中对SQL语句进行语法及语…

G1 - 生成对抗网络(GAN)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目录 理论知识生成器判别器基本原理 环境步骤环境设置数据准备模型设计模型训练模型效果展示 总结与心得体会 理论知识 生成对抗网络&#xff08;Generative …

Docker 加持的安卓手机:随身携带的知识库(一)

这篇文章聊聊&#xff0c;如何借助 Docker &#xff0c;尝试将一台五年前的手机&#xff0c;构建成一个随身携带的、本地化的知识库。 写在前面 本篇文章&#xff0c;我使用了一台去年从二手平台购入的五年前的手机&#xff0c;K20 Pro。 为了让它能够稳定持续的运行&#xf…

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

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