快捷搜索:  汽车  科技

python游戏植物大战僵尸源码:植物大战僵尸代码实现

python游戏植物大战僵尸源码:植物大战僵尸代码实现游戏实现代码的github链接 植物大战僵尸这边是csdn的下载链接 植物大战僵尸从图1和图2可以看到,僵尸的行走和攻击时的图片显示会有不同,这篇文章讲下如何进行图片显示的切换。以上面的路障僵尸为例,一共有下面几种图片类型。图3是路障僵尸的这7种图片类型的示例植物大战僵尸的图片资源比较特别,一种图片类型的每一个动作是一个单独的图片,如图4是路障僵尸带着路障攻击的动作图片,一共有11个图片,所以加载图片的代码要做对应的修改。

游戏介绍

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

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

python游戏植物大战僵尸源码:植物大战僵尸代码实现(1)

图2

python游戏植物大战僵尸源码:植物大战僵尸代码实现(2)

python游戏植物大战僵尸源码:植物大战僵尸代码实现(3)

图片显示切换


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

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

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

python游戏植物大战僵尸源码:植物大战僵尸代码实现(4)

图片加载

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


python游戏植物大战僵尸源码:植物大战僵尸代码实现(5)

完整代码

游戏实现代码的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所示。

1 def load_all_gfx(directory colorkey=c.WHITE accept=('.png' '.jpg' '.bmp' '.gif')): 2 graphics = {} 3 for name1 in os.listdir(directory): 4 # subfolders under the folder resources\graphics 5 dir1 = os.path.join(directory name1) 6 if os.path.isdir(dir1): 7 for name2 in os.listdir(dir1): 8 dir2 = os.path.join(dir1 name2) 9 if os.path.isdir(dir2): 10 # e.g. subfolders under the folder resources\graphics\Zombies 11 for name3 in os.listdir(dir2): 12 dir3 = os.path.join(dir2 name3) 13 # e.g. subfolders or pics under the folder resources\graphics\Zombies\ConeheadZombie 14 if os.path.isdir(dir3): 15 # e.g. it's the folder resources\graphics\Zombies\ConeheadZombie\ConeheadZombieAttack 16 image_name _ = os.path.splitext(name3) 17 graphics[image_name] = load_image_frames(dir3 image_name colorkey accept) 18 else: 19 # e.g. pics under the folder resources\graphics\plants\Peashooter 20 image_name _ = os.path.splitext(name2) 21 graphics[image_name] = load_image_frames(dir2 image_name colorkey accept) 22 break 23 else: 24 # e.g. pics under the folder resources\graphics\Screen 25 name ext = os.path.splitext(name2) 26 if ext.lower() in accept: 27 img = pg.image.load(dir2) 28 if img.get_alpha(): 29 img = img.convert_alpha() 30 else: 31 img = img.convert() 32 img.set_colorkey(colorkey) 33 graphics[name] = img 34 return graphics 35 36 GFX = load_all_gfx(os.path.join("resources" "graphics"))

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

1 def load_image_frames(directory image_name colorkey accept): 2 frame_list = [] 3 tmp = {} 4 # image_name is "Peashooter" pic name is 'Peashooter_1' get the index 1 5 index_start = len(image_name) 1 6 frame_num = 0; 7 for pic in os.listdir(directory): 8 name ext = os.path.splitext(pic) 9 if ext.lower() in accept: 10 index = int(name[index_start:]) 11 img = pg.image.load(os.path.join(directory pic)) 12 if img.get_alpha(): 13 img = img.convert_alpha() 14 else: 15 img = img.convert() 16 img.set_colorkey(colorkey) 17 tmp[index]= img 18 frame_num = 1 19 20 for i in range(frame_num): 21 frame_list.append(tmp[i]) 22 return frame_list

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

1 class Zombie(pg.sprite.Sprite): 2 def __init__(self x y name health head_group=None damage=1): 3 pg.sprite.Sprite.__init__(self) 4 5 self.name = name 6 self.frames = [] 7 self.frame_index = 0 8 self.loadImages() 9 self.frame_num = len(self.frames) 10 11 self.image = self.frames[self.frame_index] 12 self.rect = self.image.get_rect() 13 self.rect.centerx = x 14 self.rect.bottom = y 15 ... 16 17 def loadFrames(self frames name image_x): 18 frame_list = tool.GFX[name] 19 rect = frame_list[0].get_rect() 20 width height = rect.w rect.h 21 width -= image_x 22 23 for frame in frame_list: 24 frames.append(tool.get_image(frame image_x 0 width height))

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

update 函数:每个tick 都会调用的入口函数,用来更新僵尸的位置,切换状态和更新图片显示。
handlestate 函数:根据僵尸当前的状态来执行不同的函数。
animation 函数:每隔指定的 animate_interval 时间会显示图片类型的下一个动作。

1 def setWalk(self): 2 self.state = c.WALK 3 self.animate_interval = 150 4 5 if self.helmet: 6 self.changeFrames(self.helmet_walk_frames) 7 elif self.losHead: 8 self.changeFrames(self.losthead_walk_frames) 9 else: 10 self.changeFrames(self.walk_frames) 11 12 def setAttack(self plant): 13 self.plant = plant 14 self.state = c.ATTACK 15 self.animate_interval = 100 16 17 if self.helmet: 18 self.changeFrames(self.helmet_attack_frames) 19 elif self.losHead: 20 self.changeFrames(self.losthead_attack_frames) 21 else: 22 self.changeFrames(self.attack_frames) 23 24 def setDie(self): 25 self.state = c.DIE 26 self.animate_interval = 200 27 self.changeFrames(self.die_frames) 28 29 def changeFrames(self frames): 30 '''change image frames and modify rect position''' 31 self.frames = frames 32 self.frame_num = len(self.frames) 33 self.frame_index = 0 34 35 bottom = self.rect.bottom 36 centerx = self.rect.centerx 37 self.image = self.frames[self.frame_index] 38 self.rect = self.image.get_rect() 39 self.rect.bottom = bottom 40 self.rect.centerx = centerx

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

  • setWalk 函数:修改为行走状态,图片显示会根据不同值设置不同的图片类型。
  • setAttack 函数:修改为攻击状态,图片显示会根据不同值设置不同的图片类型。
  • setDie 函数:修改为死亡状态。
  • changeFrames 函数:修改图片类型后,需要重新设置成员变量frame_num,frame_index, image和rect的值。

1 def setWalk(self): 2 self.state = c.WALK 3 self.animate_interval = 150 4 5 if self.helmet: 6 self.changeFrames(self.helmet_walk_frames) 7 elif self.losHead: 8 self.changeFrames(self.losthead_walk_frames) 9 else: 10 self.changeFrames(self.walk_frames) 11 12 def setAttack(self plant): 13 self.plant = plant 14 self.state = c.ATTACK 15 self.animate_interval = 100 16 17 if self.helmet: 18 self.changeFrames(self.helmet_attack_frames) 19 elif self.losHead: 20 self.changeFrames(self.losthead_attack_frames) 21 else: 22 self.changeFrames(self.attack_frames) 23 24 def setDie(self): 25 self.state = c.DIE 26 self.animate_interval = 200 27 self.changeFrames(self.die_frames) 28 29 def changeFrames(self frames): 30 '''change image frames and modify rect position''' 31 self.frames = frames 32 self.frame_num = len(self.frames) 33 self.frame_index = 0 34 35 bottom = self.rect.bottom 36 centerx = self.rect.centerx 37 self.image = self.frames[self.frame_index] 38 self.rect = self.image.get_rect() 39 self.rect.bottom = bottom 40 self.rect.centerx = centerx

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

1 class ConeHeadZombie(Zombie): 2 def __init__(self x y head_group): 3 Zombie.__init__(self x y c.CONEHEAD_ZOMBIE c.CONEHEAD_HEALTH head_group) 4 self.helmet = True 5 6 def loadImages(self): 7 self.helmet_walk_frames = [] 8 self.helmet_attack_frames = [] 9 self.walk_frames = [] 10 self.attack_frames = [] 11 self.losthead_walk_frames = [] 12 self.losthead_attack_frames = [] 13 self.die_frames = [] 14 15 helmet_walk_name = self.name 16 helmet_attack_name = self.name 'Attack' 17 walk_name = c.NORMAL_ZOMBIE 18 attack_name = c.NORMAL_ZOMBIE 'Attack' 19 losthead_walk_name = c.NORMAL_ZOMBIE 'LostHead' 20 losthead_attack_name = c.NORMAL_ZOMBIE 'LostHeadAttack' 21 die_name = c.NORMAL_ZOMBIE 'Die' 22 23 frame_list = [self.helmet_walk_frames self.helmet_attack_frames 24 self.walk_frames self.attack_frames self.losthead_walk_frames 25 self.losthead_attack_frames self.die_frames] 26 name_list = [helmet_walk_name helmet_attack_name 27 walk_name attack_name losthead_walk_name 28 losthead_attack_name die_name] 29 30 for i name in enumerate(name_list): 31 self.loadFrames(frame_list[i] name tool.ZOMBIE_RECT[name]['x']) 32 33 self.frames = self.helmet_walk_frames

视频源码、素材笔记、及python相关、可关注公众号python社区营


编译环境

python3.7 pygame1.9

猜您喜欢: