导读:以前很火的植物大战僵尸游戏,本想在网上找个Python版本游戏学习下,无奈没有发现比较完整的,那就自己来写一个吧。

本文经授权转自公众号CSDN(ID:CSDNnews)

作者:marble_xu

原文链接:

https://blog.csdn.net/marble_xu/article/details/103100614

01 功能介绍

最近一直在给这个植物大战僵尸游戏添加新的植物和僵尸,因为网上的图片资源有限,能加的植物和僵尸比较少, 目前进展如下。

功能实现如下:

  • 支持的植物类型:太阳花,豌豆射手,寒冰射手,坚果,樱桃炸弹。新增加植物:双重豌豆射手,三重豌豆射手,食人花 ,小喷菇,土豆地雷,倭瓜。

  • 支持的僵尸类型:普通僵尸,旗子僵尸,路障僵尸,铁桶僵尸。新增加读报僵尸。

  • 使用json文件保存关卡信息,设置僵尸出现的时间和位置。

  • 增加每关开始时选择上场植物。

  • 增加除草机。

下面是游戏的截图:

▲图1:新增的植物和僵尸

▲图2:每关开始选择上场植物卡片

▲图3:选择植物在哪里种植

02 植物卡片选择和种植

如图3所示,游戏中可以种植物的方格一共有45个(有5行,每行9列)。

这篇文章要介绍的是:

  • 上方植物卡片栏的实现。

  • 点击植物卡片,鼠标切换为植物图片。

  • 鼠标移动时,判断当前在哪个方格中,并显示半透明的植物作为提示。

03 完整代码

游戏实现代码的github链接:

https://github.com/marblexu/PythonPlantsVsZombies

这边是csdn的下载链接:

https://download.csdn.net/download/marble_xu/11982275

04 代码实现

所有的植物卡片的名称和属性都保存在单独的list中,每个list index都对应一种植物。

比如list index 0 就是太阳花:

  • card_name_list[0] 是太阳花卡片的名字,用来获取太阳花卡片的图片。

  • plant_name_list[0] 是太阳花的名字,用来获取太阳花卡片的图片。

  • plant_sun_list[0] 是种植太阳花需要花费的太阳点数。

  • plant_frozen_time_list[0] 是太阳花的冷却时间。

代码在source\component\menubar.py中:

card_name_list = [c.CARD_SUNFLOWER, c.CARD_PEASHOOTER, c.CARD_SNOWPEASHOOTER, c.CARD_WALLNUT,c.CARD_CHERRYBOMB, c.CARD_THREEPEASHOOTER, c.CARD_REPEATERPEA, c.CARD_CHOMPER,c.CARD_PUFFMUSHROOM, c.CARD_POTATOMINE, c.CARD_SQUASH]
plant_name_list = [c.SUNFLOWER, c.PEASHOOTER, c.SNOWPEASHOOTER, c.WALLNUT,c.CHERRYBOMB, c.THREEPEASHOOTER, c.REPEATERPEA, c.CHOMPER,c.PUFFMUSHROOM, c.POTATOMINE, c.SQUASH]
plant_sun_list = [50, 100, 175, 50, 150, 325, 200, 150, 0, 25, 50]
plant_frozen_time_list = [0, 5000, 5000, 10000, 5000, 5000, 5000, 5000, 8000, 8000, 8000]
all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

05 植物卡片类

代码在source\component\menubar.py中,每个植物卡片是一个单独的Card类,用来显示这个植物。

  • checkMouseClick函数:判断鼠标是否点击到这个卡片;

  • canClick:判断这个卡片是否能种植(有没有足够的点数,是否还在冷却时间内);

  • update 函数:通过设置图片的透明度来表示这个卡片是否能选择。

class Card():def __init__(self, x, y, name_index, scale=0.78):self.loadFrame(card_name_list[name_index], scale)self.rect = self.image.get_rect()self.rect.x = xself.rect.y = yself.name_index = name_indexself.sun_cost = plant_sun_list[name_index]self.frozen_time = plant_frozen_time_list[name_index]self.frozen_timer = -self.frozen_timeself.select = Truedef loadFrame(self, name, scale):frame = tool.GFX[name]rect = frame.get_rect()width, height = rect.w, rect.hself.image = tool.get_image(frame, 0, 0, width, height, c.BLACK, scale)def checkMouseClick(self, mouse_pos):x, y = mouse_posif(x >= self.rect.x and x <= self.rect.right andy >= self.rect.y and y <= self.rect.bottom):return Truereturn Falsedef canClick(self, sun_value, current_time):if self.sun_cost <= sun_value and (current_time - self.frozen_timer) > self.frozen_time:return Truereturn Falsedef canSelect(self):return self.selectdef setSelect(self, can_select):self.select = can_selectif can_select:self.image.set_alpha(255)else:self.image.set_alpha(128)def setFrozenTime(self, current_time):self.frozen_timer = current_timedef update(self, sun_value, current_time):if (self.sun_cost > sun_value or(current_time - self.frozen_timer) <= self.frozen_time):self.image.set_alpha(128)else:self.image.set_alpha(255)def draw(self, surface):surface.blit(self.image, self.rect)

06 卡片栏类

代码在source\component\menubar.py中,MenuBar类显示图3中的植物卡片栏:

  • self.sun_value:当前采集的太阳点数;

  • self.card_list: 植物卡片的list;

  • setupCards函数:遍历初始化__init__函数中传入这个关卡选好的植物卡片list,依次创建Card类,设置每个卡片的显示位置;

  • checkCardClick函数:检查鼠标是否点击了卡片栏上的某个植物卡片,如果选择了一个可种植的卡片,返回结果。

class MenuBar():def __init__(self, card_list, sun_value):self.loadFrame(c.MENUBAR_BACKGROUND)self.rect = self.image.get_rect()self.rect.x = 10self.rect.y = 0self.sun_value = sun_valueself.card_offset_x = 32self.setupCards(card_list)def loadFrame(self, name):frame = tool.GFX[name]rect = frame.get_rect()frame_rect = (rect.x, rect.y, rect.w, rect.h)self.image = tool.get_image(tool.GFX[name], *frame_rect, c.WHITE, 1)def update(self, current_time):self.current_time = current_timefor card in self.card_list:card.update(self.sun_value, self.current_time)def createImage(self, x, y, num):if num == 1:returnimg = self.imagerect = self.image.get_rect()width = rect.wheight = rect.hself.image = pg.Surface((width * num, height)).convert()self.rect = self.image.get_rect()self.rect.x = xself.rect.y = yfor i in range(num):x = i * widthself.image.blit(img, (x,0))self.image.set_colorkey(c.BLACK)def setupCards(self, card_list):self.card_list = []x = self.card_offset_xy = 8for index in card_list:x += 55self.card_list.append(Card(x, y, index))def checkCardClick(self, mouse_pos):result = Nonefor card in self.card_list:if card.checkMouseClick(mouse_pos):if card.canClick(self.sun_value, self.current_time):result = (plant_name_list[card.name_index], card.sun_cost)breakreturn resultdef checkMenuBarClick(self, mouse_pos):x, y = mouse_posif(x >= self.rect.x and x <= self.rect.right andy >= self.rect.y and y <= self.rect.bottom):return Truereturn Falsedef decreaseSunValue(self, value):self.sun_value -= valuedef increaseSunValue(self, value):self.sun_value += valuedef setCardFrozenTime(self, plant_name):for card in self.card_list:if plant_name_list[card.name_index] == plant_name:card.setFrozenTime(self.current_time)breakdef drawSunValue(self):self.value_image = getSunValueImage(self.sun_value)self.value_rect = self.value_image.get_rect()self.value_rect.x = 21self.value_rect.y = self.rect.bottom - 21self.image.blit(self.value_image, self.value_rect)def draw(self, surface):self.drawSunValue()surface.blit(self.image, self.rect)for card in self.card_list:card.draw(surface)

07 鼠标图片切换

代码在source\state\level.py中,setupMouseImage 函数实现鼠标图片切换为选中的植物:

  • self.mouse_image :根据 plant_name 获取选中的植物图片;

  • self.mouse_rect:选中植物图片的位置,在drawMouseShow函数中,需要将植物图片的位置设置成当前鼠标的位置;

  • pg.mouse.set_visible(False):隐藏默认的鼠标显示,这样效果就是鼠标图片切换为选中的植物了。

    def setupMouseImage(self, plant_name, plant_cost):frame_list = tool.GFX[plant_name]if plant_name in tool.PLANT_RECT:data = tool.PLANT_RECT[plant_name]x, y, width, height = data['x'], data['y'], data['width'], data['height']else:x, y = 0, 0rect = frame_list[0].get_rect()width, height = rect.w, rect.hif plant_name == c.POTATOMINE or plant_name == c.SQUASH:color = c.WHITEelse:color = c.BLACKself.mouse_image = tool.get_image(frame_list[0], x, y, width, height, color, 1)self.mouse_rect = self.mouse_image.get_rect()pg.mouse.set_visible(False)self.drag_plant = Trueself.plant_name = plant_nameself.plant_cost = plant_costdef drawMouseShow(self, surface):if self.hint_plant:surface.blit(self.hint_image, self.hint_rect)x, y = pg.mouse.get_pos()self.mouse_rect.centerx = xself.mouse_rect.centery = ysurface.blit(self.mouse_image, self.mouse_rect)

08 提示种在哪个方格中

先看下map类,代码在source\component\map.py 中:

  • self.map:二维list,用来保存每个方格的状态。每个entry初始化为 0, 表示可以种植物,值为1时表示这个方格已经种了植物。

  • getMapIndex 函数:传入参数是游戏中的坐标位置(比如当前鼠标的位置),返回该位置在地图的哪个方格中。

  • getMapGridPos 函数:传入一个方格的index,返回在该方格中种植物的坐标位置。

  • showPlant 函数:根据传入的坐标位置,判断该位置所在的方格是否能种植物,如果能种,就返回返回在该方格中种植物的坐标位置。

MAP_EMPTY = 0
MAP_EXIST = 1class Map():def __init__(self, width, height):self.width = widthself.height = heightself.map = [[0 for x in range(self.width)] for y in range(self.height)]def isValid(self, map_x, map_y):if (map_x < 0 or map_x >= self.width ormap_y < 0 or map_y >= self.height):return Falsereturn Truedef isMovable(self, map_x, map_y):return (self.map[map_y][map_x] == c.MAP_EMPTY)def getMapIndex(self, x, y):x -= c.MAP_OFFSET_Xy -= c.MAP_OFFSET_Yreturn (x // c.GRID_X_SIZE, y // c.GRID_Y_SIZE)def getMapGridPos(self, map_x, map_y):return (map_x * c.GRID_X_SIZE + c.GRID_X_SIZE//2 + c.MAP_OFFSET_X,map_y * c.GRID_Y_SIZE + c.GRID_Y_SIZE//5 * 3 + c.MAP_OFFSET_Y)def setMapGridType(self, map_x, map_y, type):self.map[map_y][map_x] = typedef getRandomMapIndex(self):map_x = random.randint(0, self.width-1)map_y = random.randint(0, self.height-1)return (map_x, map_y)def showPlant(self, x, y):pos = Nonemap_x, map_y = self.getMapIndex(x, y)if self.isValid(map_x, map_y) and self.isMovable(map_x, map_y):pos = self.getMapGridPos(map_x, map_y)return pos

代码在source\state\level.py中:

  • canSeedPlant 函数:判断当前鼠标位置能否种植物;

  • setupHintImage 函数:如果当前鼠标位置能种植物,且有选择了一个植物卡片,则设置self.hint_image 显示当前会在哪一个方格中种植物,self.hint_rect 是植物种的坐标位置。

    def canSeedPlant(self):x, y = pg.mouse.get_pos()return self.map.showPlant(x, y)def setupHintImage(self):pos = self.canSeedPlant()if pos and self.mouse_image:if (self.hint_image and pos[0] == self.hint_rect.x andpos[1] == self.hint_rect.y):returnwidth, height = self.mouse_rect.w, self.mouse_rect.himage = pg.Surface([width, height])image.blit(self.mouse_image, (0, 0), (0, 0, width, height))image.set_colorkey(c.BLACK)image.set_alpha(128)self.hint_image = imageself.hint_rect = image.get_rect()self.hint_rect.centerx = pos[0]self.hint_rect.bottom = pos[1]self.hint_plant = Trueelse:self.hint_plant = False

编译环境:python3.7 + pygame1.9。

有话要说????

Q: 你还想用Python尝试做哪款游戏?

欢迎留言与大家分享

猜你想看????

  • 什么是气泡图?怎样用Python绘制?怎么用?终于有人讲明白了

  • 50年后的地球什么样?大数据、AI、量子计算的书单给你答案

  • 数据中台VS业务中台、数据中台VS数据仓库,到底有什么区别?

  • 企业数字化转型与中台建设全攻略:什么阶段进行?有哪些方法?

更多精彩????

在公众号对话框输入以下关键词

查看更多优质内容!

PPT | 报告 | 读书 | 书单 | 干货 

大数据 | 揭秘 | Python | 可视化

AI | 人工智能 | 5G | 中台

机器学习 | 深度学习 | 神经网络

合伙人 1024 | 段子 | 数学

据统计,99%的大咖都完成了这个神操作

????

觉得不错,请把这篇文章分享给你的朋友

转载 / 投稿请联系:baiyu@hzbook.com

更多精彩,请在后台点击“历史文章”查看

用 Python 实现植物大战僵尸代码相关推荐

  1. 用 Python 实现植物大战僵尸代码!

    作者 | marble_xu 责编 | 毛中政 出品 | CSDN博客 功能介绍 最近一直在给这个植物大战僵尸游戏添加新的植物和僵尸, 因为网上的图片资源有限,能加的植物和僵尸比较少, 目前进展如下. ...

  2. 涨知识!用 Python 实现植物大战僵尸代码

    作者 | marble_xu 责编 | 毛中政 出品 | CSDN博客 功能介绍 最近一直在给这个植物大战僵尸游戏添加新的植物和僵尸, 因为网上的图片资源有限,能加的植物和僵尸比较少, 目前进展如下. ...

  3. Python《植物大战僵尸》代码实现:植物卡片选择和种植

    作者 | marble_xu 来源 | CSDN原力计划获奖文章 功能介绍 植物卡片选择和种植 完整代码 代码实现 植物卡片类 卡片栏类 鼠标图片切换 提示种在哪个方格中 编译环境 功能介绍 最近一直 ...

  4. 基于python的植物大战僵尸游戏开发

    1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目,基于python的植物大战僵尸游戏开发. 计算机毕业生设计,课程设计需要帮助的可以找我 2 设计概要 21世纪是信息化时代,随着信息技术和网 ...

  5. [Python] 开发植物大战僵尸游戏

    用python开发植物大战僵尸 早期的植物大战僵尸是由vc开发的,作者的想法是非常地有特色,所以今天我们来探讨下植物大战僵尸游戏的进入场景怎么开发. 我们首需要用到如下几个文件 程序文件 功能 gam ...

  6. 卡片的sak为不支持的类型_Python 植物大战僵尸代码实现(2):植物卡片选择和种植...

    植物大战僵尸 功能介绍 最近一直在给这个植物大战僵尸游戏添加新的植物和僵尸, 因为网上的图片资源有限,能加的植物和僵尸比较少, 目前进展如下: 功能实现如下: 支持的植物类型:太阳花,豌豆射手,寒冰射 ...

  7. 【Python从零到壹】用Python实现植物大战僵尸里的面向对象

    编程的两个思想: 面向对象和面向过程 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点是:极大的降低 ...

  8. 用python实现植物大战僵尸(游戏截图+动态演示+源码分享)

    大家好,我是梦执,对梦执着.希望能和大家共同进步! 下面给大家带来python实现植物大战僵尸的的源码分享,只含有冒险模式. 截图+动态演示+源码分享 游戏截图 动态演示 源码分享 state/too ...

  9. python版植物大战僵尸源码_基于python的植物大战僵尸游戏设计与实现.docx

    湖南理工学院毕业设计(论文) PAGE PAGE 1 学 号 毕业设计(论文) 题目:基于python的植物大战僵尸游戏设计与实现 作 者 届 别 届 院 别 信息与通信工程学院 专 业 信息工程 指 ...

  10. python植物大战僵尸代码例_用Python实现植物大战僵尸游戏,很酷

    以前很火的植物大战僵尸游戏, 本想在网上找个python版本游戏学习下,无奈没有发现比较完整的,那就自己来写一个把.图片资源是从github上下载的,因为图片资源有限,只能实现几种植物和僵尸. 功能实 ...

最新文章

  1. html表格显示选择的颜色,jquery实现效果比较好的table选中行颜色
  2. 【C 语言】指针数据类型 ( 不允许向 NULL 地址写入数据 | 不允许不断地改变指针指向 | 字面量存放位置 )
  3. SpringBoot @Cacheable自定义KeyGenerator
  4. Vue中进行断点调试的两种方式(使用外部浏览器和VsCode的 Debug for Chrome插件)
  5. redhat编译安装git
  6. 【BZOJ 3229】 3229: [Sdoi2008]石子合并 (GarsiaWachs算法)
  7. Python计算一个文件中大写字母的数量
  8. oracle迁移mysql_从自建Oracle迁移至RDS MySQL
  9. 推辞掉得不是你的工作,而是你的未来
  10. php属于脚本,php是脚本语言吗
  11. java版mosquitto客户端使用SSL功能的具体操作总结
  12. jndi mysql数据库_JNDI连接数据库
  13. mysql8默认字符编码_mysql默认字符编码问题
  14. spring cloud常用组件
  15. python random模块安装_Python中的For循环和Random模块
  16. Android Studio3.0,在原有项目中进行ndk配置
  17. Linux快捷键及命令
  18. 三种存储类型和三种存储方式
  19. win系统连接交换机并设置固定ip地址
  20. VR全景智慧城市虚拟现实三维的发展

热门文章

  1. Delphi已经25岁了,我的公司每天都在使用Delphi开发跨平台的实时视频会议软件APP
  2. Windows原版系统下载地址列表
  3. 找不到任何设备驱动程序.请确保安装介质_win10安装完全手册,详细全面,新手必备...
  4. VB连接数据库SQL sever
  5. c语言扔球第一次弹10米,c语言滚动字幕代码
  6. 制作WIN_XP无人值守光盘
  7. vba正则表达式入门
  8. bt种子磁力播放器 android,(安卓)种子磁力在线播放器 — 可离线至本地
  9. android日记功能的实现6,我的android studio学习日记
  10. 伺服驱动器需要什么样的脉冲?