2023年12月3日发(作者:)

Python植物大战僵尸代码实现(1):图片加载和显示切换python 植物大战僵尸代码实现(1):图片加载和显示切换游戏介绍以前很火的植物大战僵尸游戏, 本想在网上找个python版本游戏学习下,无奈没有发现比较完整的,那就自己来写一个把。图片资源是从github上下载的,因为图片资源有限,只能实现几种植物和僵尸。功能实现如下:支持的植物类型:太阳花,豌豆射手,寒冰射手,坚果,樱桃炸弹。新增加植物:双重豌豆射手,三重豌豆射手。支持的僵尸类型:普通僵尸,棋子僵尸,路障僵尸,铁桶僵尸。使用json文件保存关卡信息,设置僵尸出现的时间和位置。新增加除草机。下面是游戏的截图:图1图2图片显示切换从图1和图2可以看到,僵尸的行走和攻击时的图片显示会有不同,这篇文章讲下如何进行图片显示的切换。以上面的路障僵尸为例,一共有下面几种图片类型。带着路障行走带着路障攻击不带路障行走(即变成普通僵尸的行走)不带路障攻击(即变成普通僵尸的攻击)没有头的行走没有头的攻击死亡图3是路障僵尸的这7种图片类型的示例图3图片加载植物大战僵尸的图片资源比较特别,一种图片类型的每一个动作是一个单独的图片,如图4是路障僵尸带着路障攻击的动作图片,一共有11个图片,所以加载图片的代码要做对应的修改。完整代码游戏实现代码的github链接

这边是csdn的下载链接代码实现这里就只讲下图片加载 和 图片显示切换的代码,整个游戏的文件目录结构和 之前的 是一样的。图片加载在 中 load_all_gfx 函数遍历resourcesgraphics 目录和子目录。代码中做了一个简单的区分:如果在resourcesgraphicssubfolder 目录中是图片,那就是单独的一个图片,比如resourcesgraphicsScreen 目录中的界面图片如果在resourcesgraphicssubfolder 目录中是子目录,那这个子目录或子子目录中的所有图片都属于一个图片类型,比如resourcesgraphicsZombiesConeheadZombieConeheadZombieAttack 目录下就是路障僵尸带着路障攻击的动作图片, 如图4所示。def load_all_gfx(directory, colorkey=, accept=('.png', '.jpg', '.bmp', '.gif')): graphics = {} for name1 in r(directory): # subfolders under the folder resourcesgraphics dir1 = (directory, name1) if (dir1): for name2 in r(dir1): dir2 = (dir1, name2) if (dir2): # e.g. subfolders under the folder resourcesgraphicsZombies for name3 in r(dir2): dir3 = (dir2, name3) # e.g. subfolders or pics under the folder resourcesgraphicsZombiesConeheadZombie if (dir3): # e.g. it's the folder resourcesgraphicsZombiesConeheadZombieConeheadZombieAttack image_name, _ = xt(name3) graphics[image_name] = load_image_frames(dir3, image_name, colorkey, accept) else: # e.g. pics under the folder resourcesgraphicsPlantsPeashooter image_name, _ = xt(name2) graphics[image_name] = load_image_frames(dir2, image_name, colorkey, accept) break else: # e.g. pics under the folder resourcesgraphicsScreen name, ext = xt(name2) if () in accept: img = (dir2) if _alpha(): img = t_alpha() else: img = t() _colorkey(colorkey) graphics[name] = img return graphicsGFX = load_all_gfx(("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 1 index_start = len(image_name) + 1

frame_num = 0; for pic in r(directory): name, ext = xt(pic) if () in accept: index = int(name[index_start:]) img = ((directory, pic)) if _alpha(): img = t_alpha() else: img = t() _colorkey(colorkey) tmp[index]= img frame_num += 1 for i in range(frame_num): frame_(tmp[i]) return frame_list图片显示切换在 中, Zombie 类是所有僵尸类的父类,初始化 函数调用loadImages函数加载所有支持的图片类型,设置Sprite 精灵类显示需要的成员变量 image和rect。loadFrames函数给具体的子类来调用,获取图片。class Zombie(): def __init__(self, x, y, name, health, head_group=None, damage=1): .__init__(self)

= name = [] _index = 0 ages() _num = len() = [_index] = _rect() x = x = y ... def loadFrames(self, frames, name, image_x): frame_list = [name] rect = frame_list[0].get_rect() width, height = rect.w, rect.h width -= image_x for frame in frame_list: (_image(frame, image_x, 0, width, height))基本的功能都在Zombie 父类中实现,如果子类有特殊需求,可以重定义同名函数。update 函数:每个tick 都会调用的入口函数,用来更新僵尸的位置,切换状态和更新图片显示。handleState 函数:根据僵尸当前的状态来执行不同的函数。animation 函数:每隔指定的 animate_interval 时间会显示图片类型的下一个动作。 def update(self, game_info): t_time = game_info[T_TIME] State() ion()

def handleState(self): if == : g() elif == : ing() elif == : ()

def animation(self): if (t_time - e_timer) > e_interval: _index += 1 if _index >= _num: if == : () return _index = 0 e_timer = t_time

= [_index]下面四个函数是修改僵尸的当前状态和图片显示。setWalk 函数:修改为行走状态,图片显示会根据不同值设置不同的图片类型。setAttack 函数:修改为攻击状态,图片显示会根据不同值设置不同的图片类型。setDie 函数:修改为死亡状态。changeFrames 函数:修改图片类型后,需要重新设置成员变量frame_num,frame_index, image和rect的值。 def setWalk(self): = e_interval = 150

if : Frames(_walk_frames) elif d: Frames(ad_walk_frames) else: Frames(_frames) def setAttack(self, plant): = plant = e_interval = 100

if : Frames(_attack_frames) elif d: Frames(ad_attack_frames) else: Frames(_frames)

def setDie(self): = e_interval = 200 Frames(_frames)

def changeFrames(self, frames): '''change image frames and modify rect position''' = frames _num = len() _index = 0

bottom = centerx = x = [_index] = _rect() = bottom x = centerx路障僵尸类就比较简单,只需要实现 loadImages 函数,调用loadFrames函数加载该种僵尸支持的图片类型,这边主要的差异在于不同种类僵尸的图片类型的名称会有区别。class ConeHeadZombie(Zombie): def __init__(self, x, y, head_group): Zombie.__init__(self, x, y, AD_ZOMBIE, AD_HEALTH, head_group) = True def loadImages(self): _walk_frames = [] _attack_frames = [] _frames = [] _frames = [] ad_walk_frames = [] ad_attack_frames = [] _frames = []

helmet_walk_name = helmet_attack_name = + 'Attack' walk_name = _ZOMBIE attack_name = _ZOMBIE + 'Attack' losthead_walk_name = _ZOMBIE + 'LostHead' losthead_attack_name = _ZOMBIE + 'LostHeadAttack' die_name = _ZOMBIE + 'Die' frame_list = [_walk_frames, _attack_frames, _frames, _frames, ad_walk_frames, ad_attack_frames, _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): ames(frame_list[i], name, _RECT[name]['x']) = _walk_frames编译环境python3.7 + pygame1.9