植物大战僵尸python实现

植物大战僵尸python实现1.0

1.简介

用python的pygame库初步实现植物大战僵尸的一些功能,并做成windows安装包。记录自己的学习过程,版本1.0
结果展示:

在这里插入图片描述

2.文件组织

文件组织如下

在这里插入图片描述

3.代码

参考代码
pz.py:
# 主程序
import time
import pygame
# 导入库
from Plants import Peashooter, SunFlower, WallNut, Plant    # 导入植物
from Other import Sun,Bullet                                # 导入太阳花和子弹
from Zoombie import Zombie,FlagZombie                       # 导入僵尸

# 参数,屏幕尺寸,背景图地址,僵尸出现的时间间隔
backgd_size = (1000,600)
bg_image_path = "material/images/background2.jpg"
sun_image_path = "material/images/SeedBank.png"
Zombie_time = 4000
# 初始化
pygame.init()
screen = pygame.display.set_mode(size=backgd_size)      # 框架大小
pygame.display.set_caption('植物大战僵尸')                # 标题
clock = pygame.time.Clock()                             # 时钟
plants_sprites = pygame.sprite.Group()                  # 植物组
sun_sprites = pygame.sprite.Group()                     # 太阳组
zoombie_sprites = pygame.sprite.Group()                 # 僵尸组
bullet_sprites = pygame.sprite.Group()                  # 子弹组
# 音乐,加载进来
pygame.mixer.init()
pygame.mixer.music.load("material/music/02 - Crazy Dave (Intro Theme).mp3")

# 定义事件,生成太阳,子弹,僵尸,旗帜僵尸
GET_SUN_EVENT = pygame.USEREVENT + 1
pygame.time.set_timer(GET_SUN_EVENT, 100)
GET_BULLET_EVENT = pygame.USEREVENT + 2
pygame.time.set_timer(GET_BULLET_EVENT, 100)
ZOOMBIE_EVENT = pygame.USEREVENT + 3
pygame.time.set_timer(ZOOMBIE_EVENT, Zombie_time)
FLAGZOOMBIE_EVENT = pygame.USEREVENT + 4
pygame.time.set_timer(FLAGZOOMBIE_EVENT, 5000)


def main(sun_value = 900,plants_list = (Peashooter, SunFlower, WallNut)):
    # 参数设置,植物被选择的下标
    choose = -1
    # 循环运行的次数记录
    index = 0
    # 读取背景地址图片
    bg_image = pygame.image.load(bg_image_path).convert_alpha()
    sun_bg_image = pygame.image.load(sun_image_path).convert_alpha()
    # 字体设定
    sun_font = pygame.font.SysFont('Arial', 20)
    # 植物卡槽
    plants_choice = [plant(None) for plant in plants_list]
    # 植物卡槽的摆放位置
    plants_weizi = [(235+51*i,7) for i in range(len(plants_choice))]

    # 每帧循环的动作操作
    while True:
        # 帧数设置
        clock.tick(20)
        # 音乐
        if not pygame.mixer.music.get_busy():
            pygame.mixer.music.play()
        # 排背景图,位置
        screen.blit(bg_image, (-100, 0))
        screen.blit(sun_bg_image, (155, 0))
        # 太阳花数量字体设置
        sum_value_surface = sun_font.render(str(sun_value), True, (0, 0, 0))
        screen.blit(sum_value_surface, (175, 60))
        # 更新卡槽
        for i in range(len(plants_choice)):
            screen.blit(plants_choice[i].pic, plants_weizi[i])
        # 如果有选择植物,鼠标下出现植物图片
        if choose >= 0:
            x, y = pygame.mouse.get_pos()
            img = plants_choice[choose].click_image
            screen.blit(img, (x-30, y-30))

        # 对事件遍历
        for event in pygame.event.get():
            # 退出
            if event.type == pygame.QUIT:
                exit()
            # 鼠标点击
            elif event.type == pygame.MOUSEBUTTONDOWN:
                # 鼠标点击判断
                pressed_key = pygame.mouse.get_pressed()
                if pressed_key[0] == 1:     # 如果是左键[1,0,0]
                    x,y = pygame.mouse.get_pos()    # 得到按键的位置

                    for weizi in plants_weizi:
                        # 点击卡槽位置判断
                        if weizi[0] < x< weizi[0]+50 and weizi[1] < y < weizi[1]+70:
                            if sun_value>=plants_choice[plants_weizi.index(weizi)].need_sun:
                                choose = plants_weizi.index(weizi)
                            else:
                                print("能量不足")
                    # 点击种植区域判断
                    if 100 < x < 900 and 80 < y < 550 and choose >= 0:
                        current = time.time()
                        plant = plants_list[choose](current)
                        plant.rect.center = (x, y)
                        plants_sprites.add(plant)
                        sun_value -= plant.need_sun
                        choose = -1
                    # 点击太阳花判断
                    for sun in sun_sprites:
                        if sun.rect.collidepoint((x,y)):
                            sun.kill()
                            sun_value += 25
                            break
            # 事件:产生太阳花
            elif event.type == GET_SUN_EVENT:
                for plants in plants_sprites:
                    if  isinstance(plants,SunFlower) and time.time() - plants.starttime >= 3:
                        sun = Sun(plants.rect)
                        sun_sprites.add(sun)
                        plants.starttime = time.time()
            # 事件子弹
            elif event.type == GET_BULLET_EVENT:
                for plants in plants_sprites:
                    if isinstance(plants, Peashooter) and time.time() - plants.starttime >= 0.8:
                        bullet = Bullet(plants.rect, backgd_size)
                        bullet_sprites.add(bullet)
                        plants.starttime = time.time()
            # 事件两个僵尸
            elif event.type == ZOOMBIE_EVENT:
                zombie = Zombie(None)
                zoombie_sprites.add(zombie)
            elif event.type == FLAGZOOMBIE_EVENT:
                flagzombie = FlagZombie(None)
                zoombie_sprites.add(flagzombie)
        # 子弹碰撞检测
        for bull in bullet_sprites:
            for zoom in zoombie_sprites:
                if pygame.sprite.collide_mask(bull,zoom):
                    bullet_sprites.remove(bull)
                    zoom.energy  -= 1
        # 植物碰撞检测
        for plants in plants_sprites:
            if isinstance(plants,Plant):
                for zoom in zoombie_sprites:
                    if pygame.sprite.collide_mask(plants,zoom):
                        zoom.ismeetplant = True
                        plants.zoombies.add(zoom)


        # 更新画面,开始下一帧
        index += 1
        plants_sprites.update(index)
        plants_sprites.draw(screen)
        zoombie_sprites.update(index)
        zoombie_sprites.draw(screen)
        bullet_sprites.update(index)
        bullet_sprites.draw(screen)
        sun_sprites.update(index)
        sun_sprites.draw(screen)
        pygame.display.update()

if __name__ == '__main__':
    plants_list = (Peashooter, SunFlower, WallNut,Peashooter,SunFlower,WallNut,Peashooter)
    main(plants_list=plants_list)
Plants.py
import pygame
import random

# 写个植物基础类,让其它植物继承
class Plant(pygame.sprite.Sprite):
    def __init__(self, starttime):      # 记录种植时间
        pygame.sprite.Sprite.__init__(self)
        # 植物在卡槽图片
        self.pic = pygame.image.load("material/images/TwinSunflower.gif").convert_alpha()
        # 植物点击的图像
        self.click_image = pygame.image.load(("material/images/SunFlower_00.png")).convert_alpha()
        # 初始图像
        self.image = pygame.image.load(("material/images/SunFlower_00.png")).convert_alpha()
        # 循环动画图像
        self.images = [pygame.image.load("material/images/SunFlower_{:02d}.png".format(i)).convert_alpha() for i
                       in range(0, 13)]
        # 被咬图片,一般不变
        self.crack_img = self.images
        # 位置信息
        self.rect = self.image.get_rect()
        # 初始化数据
        self.need_sun = 50          # 太阳需要值
        self.starttime = starttime  # 种植时间
        self.energy = 20            # 生命能量
        self.zoombies = set()       # 吃该植物的僵尸


    def update(self,*args):
        # 更新函数
        if self.energy <= 0:
            # 生命小于0,死掉
            for zoom in self.zoombies:
                # 不在阻挡僵尸
                zoom.ismeetplant = False
            # 植物消失
            self.kill()
        else:
            if self.zoombies is set():
                # 无僵尸动作
                self.image = self.images[args[0]%len(self.images)]
            else:
                # 有僵尸动作
                self.image = self.images[args[0]%len(self.images)]
            # 扣除生命值
            for zoombie in self.zoombies:
                if zoombie.isalive == True:
                    self.energy -= 1


# 太阳花,继承Plant
class  SunFlower(Plant):
    def __init__(self, starttime):
        super().__init__(starttime)
        # 卡槽图片
        self.pic = pygame.image.load("material/images/TwinSunflower.gif").convert_alpha()
        # 点击图像
        self.click_image = pygame.image.load(("material/images/SunFlower_00.png")).convert_alpha()
        # 初始图像
        self.image = pygame.image.load(("material/images/SunFlower_00.png")).convert_alpha()
        # 循环图像
        self.images = [pygame.image.load("material/images/SunFlower_{:02d}.png".format(i)).convert_alpha() for i in range(0,13)]
        # 初始化数据
        self.need_sun = 50



# 豌豆射手
class  Peashooter(Plant):
    def __init__(self, starttime):
        super().__init__(starttime)
        # 卡槽图片
        self.pic = pygame.image.load("../pz/material/images/Peashooter.gif").convert_alpha()
        # 点击图像
        self.click_image = pygame.image.load(("material/images/Peashooter_00.png")).convert_alpha()
        # 初始图像
        self.image = pygame.image.load(("material/images/Peashooter_00.png")).convert_alpha()
        # 循环图像
        self.images = [pygame.image.load("material/images/Peashooter_{:02d}.png".format(i)).convert_alpha() for i in range(0,13)]
        # 初始化数据
        self.need_sun = 100


# 坚果
class  WallNut(Plant):
    def __init__(self, starttime):
        super().__init__(starttime)
        # 卡槽图片
        self.pic = pygame.image.load("../pz/material/images/WallNut.gif").convert_alpha()
        # 点击图像
        self.click_image = pygame.image.load(("material/images/WallNut_00.png")).convert_alpha()
        # 初始图像
        self.image = pygame.image.load(("material/images/WallNut_00.png")).convert_alpha()
        # 循环图像
        self.images = [pygame.image.load("material/images/WallNut_{:02d}.png".format(i)).convert_alpha() for i in
                       range(0, 13)]
        # 坚果被咬图像
        self.crack_img = [
            pygame.transform.smoothscale(pygame.image.load(("material/images/Wallnut_body.png")).convert_alpha(),   # 图像读取,并缩放
                                         (self.image.get_rect().width,self.image.get_rect().height)),
            pygame.transform.smoothscale(pygame.image.load(("material/images/Wallnut_cracked1.png")).convert_alpha(),
                                         (self.image.get_rect().width,self.image.get_rect().height)),
            pygame.transform.smoothscale(pygame.image.load(("material/images/Wallnut_cracked2.png")).convert_alpha(),
                                         (self.image.get_rect().width,self.image.get_rect().height)),]
        # 初始化数据
        self.need_sun = 50
        self.energy = 50


    def update(self,*args):
        # 坚果图像动画不同,重写类
        if self.energy <= 0:
            # 死亡
            for zoom in self.zoombies:
                zoom.ismeetplant = False
            self.kill()
        else:
            # 不同生命值,不同动画
            if self.energy >= 40:
                self.image = self.images[args[0]%len(self.images)]
            elif 30<=self.energy < 40:
                self.image = self.crack_img[0]
            elif 20 <= self.energy < 30:
                self.image = self.crack_img[1]
            else:
                self.image = self.crack_img[2]
            # 被僵尸吃,扣血
            for zoombie in self.zoombies:
                if zoombie.isalive == True:
                    self.energy -= 1
Zoombie.py:
import pygame
import random

# 僵尸类
class  Zombie(pygame.sprite.Sprite):
    def __init__(self,starttime):
        pygame.sprite.Sprite.__init__(self)
        # 图片
        self.image = pygame.image.load(("material/images/Zombie_0.png")).convert_alpha()
        self.images = [pygame.image.load("material/images/Zombie_{}.png".format(i)).convert_alpha() for i in range(0,22)]
        self.dieimages = [pygame.image.load("material/images/ZombieDie_{}.png".format(i)).convert_alpha() for i in range(0,10)]
        self.attact_images = [pygame.image.load("material/images/ZombieAttack_{}.png".format(i)).convert_alpha() for i in range(0,21)]
        # 位置
        self.rect = self.image.get_rect()
        self.rect.top = random.randrange(0,5)*100+25
        self.rect.left = 900
        # 初始化信息
        self.speed = 2
        self.energy = 6
        self.dietimes = 0
        self.ismeetplant = False
        self.isalive = True

    def update(self,*args):
        # 活着
        if self.energy >= 0:
            # 前面有植物
            if self.ismeetplant:
                self.image = self.attact_images[args[0] % len(self.attact_images)]
            else:       # 前面没有植物
                self.image = self.images[args[0] % len(self.images)]
                if self.rect.left >= 100:
                    self.rect.left -= self.speed
        # 死亡
        else:
            self.isalive = False
            if self.dietimes < 20:
                self.image = self.dieimages[self.dietimes//2]
                self.dietimes += 1
            else:
                if self.dietimes > 35:
                    self.kill()
                else:
                    self.dietimes += 1

# 旗帜僵尸
class  FlagZombie(Zombie):
    def __init__(self,starttime):
        Zombie.__init__(self,starttime)
        self.image = pygame.image.load(("material/images/FlagZombie_0.png")).convert_alpha()
        self.images = [pygame.image.load("material/images/FlagZombie_{}.png".format(i)).convert_alpha() for i in range(0,12)]

        self.energy = 10
Others.py:
import pygame
import random

# 太阳花
class  Sun(pygame.sprite.Sprite):
    def __init__(self,rect):
        pygame.sprite.Sprite.__init__(self)
        # 加载图片
        self.image = pygame.image.load(("material/images/Sun_1.png")).convert_alpha()
        self.images = [pygame.image.load("material/images/Sun_{}.png".format(i)).convert_alpha() for i in range(1, 18)]
        # 位置信息
        self.rect = self.images[0].get_rect()
        self.rect.top = rect.top + random.randint(-50, 50)
        self.rect.left = rect.left + random.randint(-50, 50)

    # 更新图像
    def update(self,*args):
        self.image = self.images[args[0]%len(self.images)]



# 子弹
class  Bullet(pygame.sprite.Sprite):
    # 豌豆子弹
    def __init__(self,rect,bg_size,dir=True):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(("material/images/Bullet_1.png")).convert_alpha()
        self.rect = self.image.get_rect()
        # 子弹的初始化位置
        self.rect.top = rect.top
        self.rect.left = rect.left + 25
        self.width = bg_size[0]
        self.speed = 7

    def update(self,*args):
        if self.rect.right < self.width:
            self.rect.left += self.speed
        else:
            self.kill()

4.打包程序

"""
pyinstaller打包游戏的方法:
1.在命令窗口安装pyinstaller
pip install pyinstaller
2.查看安装的版本信息
pyinstaller -v
3.进入需要打包的文件的路径下
pyinstaller -F -w pz.py -p Plants.py -p Other.py -p Zoombie.py
备注:pyinstaller -F -w 程序入口文件 -p 程序文件 -p 程序文件
装了conda 的应运行:
conda remove pathlib
不能解决运行
 # python -m pip install pathlib
解决警告问题
"""
运行pyinstaller -F -w pz.py -p Plants.py -p Other.py -p Zoombie.py 命令后目录如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

与直接运行pz.py效果一样

在这里插入图片描述
最后用inno setup将exe做成安装包
在这里插入图片描述在这里插入图片描述
正常运行
在这里插入图片描述
参考资料

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值