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

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

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Python的LSTM网络实现单特征预测回归任务(TensorFlow)

目录 一、数据集 二、任务目标 三、代码实现 1、从本地路径中读取数据文件 2、数据归一化 3、创建配置类&#xff0c;将LSTM的各个超参数声明为变量&#xff0c;便于后续使用 4、创建时间序列数据 5、划分数据集 6、定义LSTM网络 &#xff08;1&#xff09;创建顺序模…

【深度学习】第一门课 神经网络和深度学习 Week 4 深层神经网络

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;深度学习 &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对…

G1 - 生成对抗网络(GAN)

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

Jenkins流水线部署springboot项目

文章目录 Jenkins流水线任务介绍Jenkins流水线任务构建Jenkins流水线任务Groovy脚本Jenkinsfile实现 Jenkins流水线任务实现参数化构建拉取Git代码构建代码制作自定义镜像并发布 Jenkins流水线任务介绍 之前采用Jenkins的自由风格构建的项目&#xff0c;每个步骤流程都要通过不…

二维数组的鞍点(C语言)

一、鞍点解释&#xff1b; 鞍点就是该位置上的元素在该行上最大、在该列上最小&#xff1b; 二、N-S流程图&#xff1b; 三、运行结果&#xff1b; 四、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff…

Java_JVM_JVMs

JVM 官方文档说明文档目录 官方文档 JVM Specification 说明 以Java SE 17为标准 文档目录 2&#xff1a;JVM 结构 class文件数据类型 基本数据类型引用数据类型 运行时数据区 栈帧 其他内容 对象的表示浮点数运算特殊方法 初始化方法【实例、类】多态方法 3&#xff…

AI代理架构的发展:从单一到多代理系统的演进及其影响分析

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Python中无法pip的解决办法和pip的介绍

什么是pip&#xff1f; PIP是通用的Python包管理工具&#xff0c;提供了对 Python 包的查找、下载、安装、卸载、更新等功能。安装诸如Pygame、Pymysql、requests、Django等Python包时&#xff0c;都要用到pip。 注意&#xff1a;在Python3.4&#xff08;一说是3.6&#xff09…

自动化滇医通

###我已经将数据爬取出来### 现在开源集合大家的思路一起研究 &#xff08;请更换ip 以及 暂停时间 不然会提示违规操作&#xff09; 脚本读取预约信息后开始随机抢一家的&#xff0c;qiang方法里面请自行修改抓包数据参数&#xff01;&#xff01; 现在开源大家一起讨论 pyt…

富文本编辑器 iOS

https://gitee.com/klkxxy/WGEditor-mobile#wgeditor-mobile 采用iOS系统浏览器做的一款富文本编辑器工具。 原理就是使用WKWebView加载一个本地的一个html文件&#xff0c;从而达到编辑器功能的效果&#xff01; 由于浏览器的一些特性等&#xff0c;富文本编辑器手机端很难做…

【开源物联网平台】window环境下搭建调试监控设备环境

&#x1f308; 个人主页&#xff1a;帐篷Li &#x1f525; 系列专栏&#xff1a;FastBee物联网开源项目 &#x1f4aa;&#x1f3fb; 专注于简单&#xff0c;易用&#xff0c;可拓展&#xff0c;低成本商业化的AIOT物联网解决方案 目录 一、使用docker脚本部署zlmediakit 1.1 …

WebDriver使用带用户名密码验证的IP代理解决方案

背景&#xff0c;使用python3 selenium 先定义一个方法&#xff0c;这里主要用到了chrome插件的功能&#xff0c;利用这个插件来放进代理内容。 def create_proxy_auth_extension(proxy_host, proxy_port,proxy_username, proxy_password, schemehttp):manifest_json "…

【HAL库 STM32】输入捕获并实现超声波测距

文章目录 HC-SR04 超声波模块简介HC-SR04 工作原理如何使用HC-SR04模块程序效果 一、工程配置代码如果您发现文章有错误请与我留言&#xff0c;感谢 HC-SR04 超声波模块简介 HC-SR04 工作原理 模块有2个超声波换能器&#xff08;如图所示&#xff09;&#xff0c;一个发出声波…

Spark Stream

一、Spark Streaming是什么 Spark Streaming 用于流式数据的处理。Spark Streaming 支持的数据输入源很多&#xff0c;例如&#xff1a;Kafka、Flume、Twitter、ZeroMQ 和简单的 TCP 套接字等等。数据输入后可以用 Spark 的高度抽象原语如&#xff1a;map、reduce、join、wind…

基于SSM SpringBoot vue教务排课系统

基于SSM SpringBoot vue教务排课系统 系统功能 登录 个人中心 学生信息管理 教师信息管理 课室信息管理 班级信息管理 系别信息管理 专业信息管理 课程信息管理 选课信息管理 课表信息管理 开发环境和技术 开发语言&#xff1a;Java 使用框架: SSM(Spring SpringMVC Myba…

✔ ★Java大项目——用Java模拟RabbitMQ实现一个消息队列(二)【创建核心类、封装数据库操作】

✔ ★Java大项目——用Java模拟RabbitMQ实现一个消息队列 四. 项⽬创建五. 创建核⼼类 ★创建 Exchange&#xff08;名字、类型、持久化、自动删除、参数&#xff09;创建 MSGQueue&#xff08;名字、持久化、独占标识&#xff09;创建 Binding&#xff08;交换机名字、队列名字…

pymeshlab加载物体、创建UV映射(基于平面投影)、创建并保存UV纹理和物体模型

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。本文所给出的例子是https://download.csdn.net/download/weixin_42605076/89233917中的…

MySQL45讲(一)(40)

回顾binlog_formatstatement STATEMENT 记录SQL语句。日志文件小&#xff0c;节约IO&#xff0c;但是对一些系统函数不能准确复制或不能复制&#xff0c;如now()、uuid()等 在RR隔离级别下&#xff0c;binlog_formatstatement 如果执行insert select from 这条语句是对于一张…

uniapp 自定义相机插件(组件版、缩放、裁剪)组件 Ba-CameraView

自定义相机插件&#xff08;组件版、缩放、裁剪&#xff09; Ba-CameraView 简介&#xff08;下载地址&#xff09; Ba-CameraView 是一款自定义相机拍照组件&#xff0c;支持任意界面&#xff0c;支持裁剪 支持任意自定义界面支持手势缩放支持裁剪&#xff08;手势拖动、比…

35.Docker-数据卷,目录挂载

注意&#xff1a;在容器内修改文件是不推荐的。 1.修改不方便&#xff0c;比如vi命令都无法使用。 2.容器内修改&#xff0c;没有日志记录的。 问题&#xff1a;那应该如何修改容器中的文件呢&#xff1f; 数据卷 volume是一个虚拟目录&#xff0c;指向宿主机文件系统中的…