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

news/2024/11/28 1:50:37/

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

  • 游戏介绍
    • 图片显示切换
    • 图片加载
    • 完整代码
  • 代码实现
    • 图片加载
    • 图片显示切换
    • 编译环境

游戏介绍

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

  • 支持的植物类型:太阳花,豌豆射手,寒冰射手,坚果,樱桃炸弹。新增加植物:双重豌豆射手,三重豌豆射手。
  • 支持的僵尸类型:普通僵尸,棋子僵尸,路障僵尸,铁桶僵尸。
  • 使用json文件保存关卡信息,设置僵尸出现的时间和位置。
  • 新增加除草机。

下面是游戏的截图:
图1demo1
图2demo2
demo3

图片显示切换

从图1和图2可以看到,僵尸的行走和攻击时的图片显示会有不同,这篇文章讲下如何进行图片显示的切换。
以上面的路障僵尸为例,一共有下面几种图片类型。

  • 带着路障行走
  • 带着路障攻击
  • 不带路障行走(即变成普通僵尸的行走)
  • 不带路障攻击(即变成普通僵尸的攻击)
  • 没有头的行走
  • 没有头的攻击
  • 死亡

图3是路障僵尸的这7种图片类型的示例
图3图片类型

图片加载

植物大战僵尸的图片资源比较特别,一种图片类型的每一个动作是一个单独的图片,如图4是路障僵尸带着路障攻击的动作图片,一共有11个图片,所以加载图片的代码要做对应的修改。
action

完整代码

游戏实现代码的github链接 植物大战僵尸
这边是csdn的下载链接 植物大战僵尸

代码实现

这里就只讲下图片加载 和 图片显示切换的代码,整个游戏的文件目录结构和 之前的 超级玛丽 是一样的。

图片加载

在 source\tool.py 中 load_all_gfx 函数遍历resources\graphics 目录和子目录。
代码中做了一个简单的区分:

  • 如果在resources\graphics\subfolder\ 目录中是图片,那就是单独的一个图片,比如resources\graphics\Screen 目录中的界面图片
  • 如果在resources\graphics\subfolder\ 目录中是子目录,那这个子目录或子子目录中的所有图片都属于一个图片类型,比如resources\graphics\Zombies\ConeheadZombie\ConeheadZombieAttack 目录下就是路障僵尸带着路障攻击的动作图片, 如图4所示。
def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '.gif')):graphics = {}for name1 in os.listdir(directory):# subfolders under the folder resources\graphicsdir1 = os.path.join(directory, name1)if os.path.isdir(dir1):for name2 in os.listdir(dir1):dir2 = os.path.join(dir1, name2)if os.path.isdir(dir2):# e.g. subfolders under the folder resources\graphics\Zombiesfor name3 in os.listdir(dir2):dir3 = os.path.join(dir2, name3)# e.g. subfolders or pics under the folder resources\graphics\Zombies\ConeheadZombieif os.path.isdir(dir3):# e.g. it's the folder resources\graphics\Zombies\ConeheadZombie\ConeheadZombieAttackimage_name, _ = os.path.splitext(name3)graphics[image_name] = load_image_frames(dir3, image_name, colorkey, accept)else:# e.g. pics under the folder resources\graphics\Plants\Peashooterimage_name, _ = os.path.splitext(name2)graphics[image_name] = load_image_frames(dir2, image_name, colorkey, accept)breakelse:# e.g. pics under the folder resources\graphics\Screenname, ext = os.path.splitext(name2)if ext.lower() in accept:img = pg.image.load(dir2)if img.get_alpha():img = img.convert_alpha()else:img = img.convert()img.set_colorkey(colorkey)graphics[name] = imgreturn graphicsGFX = load_all_gfx(os.path.join("resources","graphics"))

load_image_frames 函数 将目录中的所有图片按照 图片名称中的index值为key,保存在tmp 字典中。比如图片名称为"ConeheadZombieAttack_2", 它的index值就为2。
然后将图片按index值依次加入到 frame_list 中。

def load_image_frames(directory, image_name, colorkey, accept):frame_list = []tmp = {}# image_name is "Peashooter", pic name is 'Peashooter_1', get the index 1index_start = len(image_name) + 1 frame_num = 0;for pic in os.listdir(directory):name, ext = os.path.splitext(pic)if ext.lower() in accept:index = int(name[index_start:])img = pg.image.load(os.path.join(directory, pic))if img.get_alpha():img = img.convert_alpha()else:img = img.convert()img.set_colorkey(colorkey)tmp[index]= imgframe_num += 1for i in range(frame_num):frame_list.append(tmp[i])return frame_list

图片显示切换

在 source\component\zombie.py 中, Zombie 类是所有僵尸类的父类,初始化 函数调用loadImages函数加载所有支持的图片类型,设置Sprite 精灵类显示需要的成员变量 image和rect。
loadFrames函数给具体的子类来调用,获取图片。

class Zombie(pg.sprite.Sprite):def __init__(self, x, y, name, health, head_group=None, damage=1):pg.sprite.Sprite.__init__(self)self.name = nameself.frames = []self.frame_index = 0self.loadImages()self.frame_num = len(self.frames)self.image = self.frames[self.frame_index]self.rect = self.image.get_rect()self.rect.centerx = xself.rect.bottom = y...def loadFrames(self, frames, name, image_x):frame_list = tool.GFX[name]rect = frame_list[0].get_rect()width, height = rect.w, rect.hwidth -= image_xfor frame in frame_list:frames.append(tool.get_image(frame, image_x, 0, width, height))

基本的功能都在Zombie 父类中实现,如果子类有特殊需求,可以重定义同名函数。

  • update 函数:每个tick 都会调用的入口函数,用来更新僵尸的位置,切换状态和更新图片显示。
  • handleState 函数:根据僵尸当前的状态来执行不同的函数。
  • animation 函数:每隔指定的 animate_interval 时间会显示图片类型的下一个动作。
    def update(self, game_info):self.current_time = game_info[c.CURRENT_TIME]self.handleState()self.animation()def handleState(self):if self.state == c.WALK:self.walking()elif self.state == c.ATTACK:self.attacking()elif self.state == c.DIE:self.dying()def animation(self):if (self.current_time - self.animate_timer) > self.animate_interval:self.frame_index += 1if self.frame_index >= self.frame_num:if self.state == c.DIE:self.kill()returnself.frame_index = 0self.animate_timer = self.current_timeself.image = self.frames[self.frame_index]

下面四个函数是修改僵尸的当前状态和图片显示。

  • setWalk 函数:修改为行走状态,图片显示会根据不同值设置不同的图片类型。
  • setAttack 函数:修改为攻击状态,图片显示会根据不同值设置不同的图片类型。
  • setDie 函数:修改为死亡状态。
  • changeFrames 函数:修改图片类型后,需要重新设置成员变量frame_num,frame_index, image和rect的值。
    def setWalk(self):self.state = c.WALKself.animate_interval = 150if self.helmet:self.changeFrames(self.helmet_walk_frames)elif self.losHead:self.changeFrames(self.losthead_walk_frames)else:self.changeFrames(self.walk_frames)def setAttack(self, plant):self.plant = plantself.state = c.ATTACKself.animate_interval = 100if self.helmet:self.changeFrames(self.helmet_attack_frames)elif self.losHead:self.changeFrames(self.losthead_attack_frames)else:self.changeFrames(self.attack_frames)def setDie(self):self.state = c.DIEself.animate_interval = 200self.changeFrames(self.die_frames)def changeFrames(self, frames):'''change image frames and modify rect position'''self.frames = framesself.frame_num = len(self.frames)self.frame_index = 0bottom = self.rect.bottomcenterx = self.rect.centerxself.image = self.frames[self.frame_index]self.rect = self.image.get_rect()self.rect.bottom = bottomself.rect.centerx = centerx

路障僵尸类就比较简单,只需要实现 loadImages 函数,调用loadFrames函数加载该种僵尸支持的图片类型,这边主要的差异在于不同种类僵尸的图片类型的名称会有区别。

class ConeHeadZombie(Zombie):def __init__(self, x, y, head_group):Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, c.CONEHEAD_HEALTH, head_group)self.helmet = Truedef loadImages(self):self.helmet_walk_frames = []self.helmet_attack_frames = []self.walk_frames = []self.attack_frames = []self.losthead_walk_frames = []self.losthead_attack_frames = []self.die_frames = []helmet_walk_name = self.namehelmet_attack_name = self.name + 'Attack'walk_name = c.NORMAL_ZOMBIEattack_name = c.NORMAL_ZOMBIE + 'Attack'losthead_walk_name = c.NORMAL_ZOMBIE + 'LostHead'losthead_attack_name = c.NORMAL_ZOMBIE + 'LostHeadAttack'die_name = c.NORMAL_ZOMBIE + 'Die'frame_list = [self.helmet_walk_frames, self.helmet_attack_frames,self.walk_frames, self.attack_frames, self.losthead_walk_frames,self.losthead_attack_frames, self.die_frames]name_list = [helmet_walk_name, helmet_attack_name,walk_name, attack_name, losthead_walk_name,losthead_attack_name, die_name]for i, name in enumerate(name_list):self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])self.frames = self.helmet_walk_frames

编译环境

python3.7 + pygame1.9


http://www.ppmy.cn/news/715604.html

相关文章

利用百度图像识别鉴定植物

利用百度图像识别进行植物识别 前端页面代码index.js(需要用到的js代码)后端(Java)接收并上传给百度图像识别 最近在学校课比较少,看了下百度的图像识别,我的想法是在客服端浏览器上传植物图片,…

有什么拍照识别植物的软件?建议收藏这几个软件

在我们日常生活中,经常会接触到各种植物,比如去公园游玩的时候,或者是去花鸟市场的时候。有时看到一些美丽的植物,但是我们却不认识植物叫什么,这种感觉就非常难受。所以为了解决这个问题,今天我就给大家带…

SAP 查询字段所存在的表(增强定义)

T-CODE——axtshow DATA:lv_zzbranch TYPE ze_les_branch, ls_aet088 TYPE zlesaet088_bol_attr, lr_adminh TYPE REF TO cl_crm_bol_entity. lr_entity_relationv TYPE REF TO cl_crm_bol_entity. lr_entity_relationv lr_adminh->get_related_entity( …

图片识别,人脸识别,植物识别,花卉识别,签到小程序,借助百度AI智能识别功能实现图片识别,人脸识别小程序

一,人脸签到效果图 我们做人脸识别签到,其实就是要拿识别的人脸和数据库里的人脸对比,相识度大于一定的值,就可以判定成功。 如我们识别的结果是98.295%,所以这里就可以认定为签到成功 1-1,效果图 1-1-…

植物识别扫一扫的软件有哪些?植物识别软件推荐。

植物识别扫一扫的软件有哪些?相信非常多的小伙伴,日常出门在外的时候,经常会碰到一些不认识的花花草草,出于我们的好奇心,我们通常都非常想知道不认识的这些花花草草,究竟叫什么,那么这时候我们…

使用OpenCV-python对植物图片进行分类

文章目录 图片分类的思路和需要加载的库函数说明核心代码分析数据预处理:文件处理和命名匹配数据预处理:特征提取和标签提取学习模型:数据划分和模型训练预测输出:利用训练好的模型进行图片分类 完整代码附录和运行结果 图片分类的…

如何通过图片识别植物?识别植物软件有哪些?

想必大家都有这样的经历,当我们在外面散步时,看到一种美丽的植物,但是却不知道它的名字。现在,有一种神奇的技术可以帮助我们解决这个问题,那就是通过图片识别植物。现在你只需要拍下这种植物的照片,然后上…

认识植物 —— 花

说句扫兴的话,花朵是植物的性器官,用于授粉,结籽。 虞美人是一种词牌名,也是一种花卉;玫瑰和月季都是蔷薇科植物; 1. 花瓣的数量 五个花瓣(报春花(左),杏花…