作者 | marble_xu

来源 | CSDN原力计划获奖文章

  • 功能介绍

    • 植物卡片选择和种植

    • 完整代码

  • 代码实现

    • 植物卡片类

    • 卡片栏类

    • 鼠标图片切换

    • 提示种在哪个方格中

    • 编译环境

    • 功能介绍

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

功能介绍

功能实现如下:

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

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

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

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

  • 增加除草机。

Python 植物大战僵尸代码实现(1):图片加载和显示切换

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

下面是游戏的截图:

图1:新增的植物和僵尸

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

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

植物卡片选择和种植

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

这篇文章要介绍的是:

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

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

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

完整代码

游戏实现代码的github链接 植物大战僵尸

https://github.com/marblexu/PythonPlantsVsZombies

这边是csdn的下载链接 植物大战僵尸

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

代码实现

所有的植物卡片的名称和属性都保存在单独的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]

植物卡片类

代码在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)

卡片栏类

代码在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)

鼠标图片切换

代码在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)

提示种在哪个方格中

先看下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

版权声明:本文为CSDN博主「marble_xu」原创,版权归作者所有。

技术的道路一个人走着极为艰难?

一身的本领得不施展?

优质的文章得不到曝光?

别担心,

即刻起,CSDN 将为你带来创新创造创变展现的大舞台,

扫描下方二维码,欢迎加入 CSDN 「原力计划」!

推荐阅读

  • 数学学渣必备!拍照上传,分步求解,微软解题神器拯救你

  • 华为诺亚方舟开源预训练模型“哪吒”,4项任务均达到SOTA

  • 蚂蚁金服提新概率图模型GLN,正确率提升8.2%,具备可解释性 | NeurIPS 2019

  • 赠书 | 熵的实际应用,赌场和金融圈最著名的一个数学公式

  • 那些打着AI万金油旗号的产品欺骗大众,如何识别?

  • 扛住100亿次请求——如何做一个“有把握”的春晚红包系统

  • 「刷新 CTO」微软与 CSDN 的 CTO 转型思想汇

  • 想开发智能合约?先 get 下这个适合所有人的模型驱动法(文末有福利)

  • 你点的每个“在看”,我都认真当成了AI

Python《植物大战僵尸》代码实现:植物卡片选择和种植相关推荐

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

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

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

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

  3. 【Unity植物大战僵尸】UI植物卡片逻辑完善(十二)

    目录 22.UI植物卡片逻辑完善 问题一:植物的生命值和最大生命值 问题二:将一些变量和官方变量一致 问题三:点击卡片后还可以继续点击,进而种植多个植物 问题四:如何得到卡片的状态,也就是点击卡片后( ...

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

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

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

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

  6. 第5课python植物大战僵尸-添加豌豆射手类

    提示:第5课python植物大战僵尸-添加豌豆射手类 文章目录 摘要 一.豌豆射手类 Peashooter 1.import导入pygame模块 2.定义一个豌豆射手的类型,不用继承任何的类 3.定义 ...

  7. python植物大战僵尸辅助器手机版_GitHub又放大招,Python版本的植物大战僵尸还能作弊玩!...

    <植物大战僵尸>游戏它是一款极富策略性的小游戏,集成了即时战略.塔防御战和卡片收集等要素,玩家控制植物抵御僵尸的进攻,保护这片植物园.记得小编刚工作的时候抱着IPAD经常玩到深夜. 最近在 ...

  8. python植物大战僵尸(1)

    欢迎加入我们卧虎藏龙的python讨论qq群:729683466 ●导 语 ● 之前一直发一些简单的小游戏 百十行代码的那种 估计大家已经了解的一清二楚了 现在可以讲一些比较复杂的游戏 今天就带领大家 ...

  9. 第4课python植物大战僵尸-绘制背景

    摘要 1.新建material文件夹,在该文件下新建images和music,这两个文件存放音乐和图片,还有声音的处理. 2.新建python文件(plant_vs_zoomie_game_norma ...

最新文章

  1. shell 动态进程守护
  2. Eclipse如何提高开发效率(转)
  3. OpenCV蒙版图像make mask image的实例(附完整代码)
  4. 如何做一场高质量的分享?
  5. Java用JSONObject-lib来解析json串
  6. cocos2dx基础篇(2)——Win32移植到Android
  7. 人为什么必须积极有为?
  8. Django——百知听课笔记一
  9. asp.net MVC错误:uses 'System.Web.WebPages, Version=2.0.0.0, ....which has a higher version...
  10. forEach、for...in、for...of
  11. java se 试题_javaSE试题
  12. 这四款录屏工具,也许是电脑录屏软件中免费、无广告且最实用的
  13. java基于t-io框架实现区块链中的p2p网络构建模拟区块信息同步
  14. hp打印机没有右键扫描_win10打印机右键没有‘开始扫描’的修复办法
  15. 英特尔处理器后缀字母的意思
  16. Render函数渲染页面
  17. 多表联查时的条件筛选
  18. 云主机和电脑主机服务器有什么区别?
  19. javascript百炼成仙 第一章 掌握JavaScript基础1.8 对象的取值
  20. 新业务员如何开发外贸客户?

热门文章

  1. buuctf 黑客帝国 解析
  2. 基于探路者算法的函数寻优算法
  3. distinct 、group by 的区别
  4. 【软著流程】软件著作权登记流程
  5. 大幅面柔性印刷线路板缺陷在线视觉检测系统设计
  6. C++构造函数的幕后工作
  7. php 公众号支付文档,【微信支付】公众号支付开发者文档
  8. 关于PHP5.3访问ECSHOP系统_手机版本出错问题
  9. thinkphp5使html5实现动态跳转
  10. symbian创建新的接入点