游戏介绍

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

功能实现如下:

支持的植物类型:太阳花,豌豆射手,寒冰射手,坚果,樱桃炸弹。新增加植物:双重豌豆射手,三重豌豆射手。

支持的僵尸类型:普通僵尸,棋子僵尸,路障僵尸,铁桶僵尸。

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

新增加除草机。

下面是游戏的截图:

图1

图2

图片显示切换

从图1和图2可以看到,僵尸的行走和攻击时的图片显示会有不同,这篇文章讲下如何进行图片显示的切换。

以上面的路障僵尸为例,一共有下面几种图片类型。

带着路障行走

带着路障攻击

不带路障行走(即变成普通僵尸的行走)

不带路障攻击(即变成普通僵尸的攻击)

没有头的行走

没有头的攻击

死亡

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

图片加载

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

完整代码

游戏实现代码的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 inos.listdir(directory):4 #subfolders under the folder resources\graphics

5 dir1 =os.path.join(directory, name1)6 ifos.path.isdir(dir1):7 for name2 inos.listdir(dir1):8 dir2 =os.path.join(dir1, name2)9 ifos.path.isdir(dir2):10 #e.g. subfolders under the folder resources\graphics\Zombies

11 for name3 inos.listdir(dir2):12 dir3 =os.path.join(dir2, name3)13 #e.g. subfolders or pics under the folder resources\graphics\Zombies\ConeheadZombie

14 ifos.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() inaccept:27 img =pg.image.load(dir2)28 ifimg.get_alpha():29 img =img.convert_alpha()30 else:31 img =img.convert()32 img.set_colorkey(colorkey)33 graphics[name] =img34 returngraphics35

36 GFX = load_all_gfx(os.path.join("resources","graphics"))

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

然后将图片按index值依次加入到 frame_list 中。

1 defload_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 inos.listdir(directory):8 name, ext =os.path.splitext(pic)9 if ext.lower() inaccept:10 index =int(name[index_start:])11 img =pg.image.load(os.path.join(directory, pic))12 ifimg.get_alpha():13 img =img.convert_alpha()14 else:15 img =img.convert()16 img.set_colorkey(colorkey)17 tmp[index]=img18 frame_num += 1

19

20 for i inrange(frame_num):21 frame_list.append(tmp[i])22 return frame_list

图片显示切换

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

loadFrames函数给具体的子类来调用,获取图片。

1 classZombie(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 =name6 self.frames =[]7 self.frame_index =08 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 =x14 self.rect.bottom =y15 ...16

17 defloadFrames(self, frames, name, image_x):18 frame_list =tool.GFX[name]19 rect =frame_list[0].get_rect()20 width, height =rect.w, rect.h21 width -=image_x22

23 for frame inframe_list:24 frames.append(tool.get_image(frame, image_x, 0, width, height))

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

update 函数:每个tick 都会调用的入口函数,用来更新僵尸的位置,切换状态和更新图片显示。

handleState 函数:根据僵尸当前的状态来执行不同的函数。

animation 函数:每隔指定的 animate_interval 时间会显示图片类型的下一个动作。

1 defupdate(self, game_info):2 self.current_time =game_info[c.CURRENT_TIME]3 self.handleState()4 self.animation()5

6 defhandleState(self):7 if self.state ==c.WALK:8 self.walking()9 elif self.state ==c.ATTACK:10 self.attacking()11 elif self.state ==c.DIE:12 self.dying()13

14 defanimation(self):15 if (self.current_time - self.animate_timer) >self.animate_interval:16 self.frame_index += 1

17 if self.frame_index >=self.frame_num:18 if self.state ==c.DIE:19 self.kill()20 return

21 self.frame_index =022 self.animate_timer =self.current_time23

24 self.image = self.frames[self.frame_index]

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

setWalk 函数:修改为行走状态,图片显示会根据不同值设置不同的图片类型。

setAttack 函数:修改为攻击状态,图片显示会根据不同值设置不同的图片类型。

setDie 函数:修改为死亡状态。

changeFrames 函数:修改图片类型后,需要重新设置成员变量frame_num,frame_index, image和rect的值。

1 defsetWalk(self):2 self.state =c.WALK3 self.animate_interval = 150

4

5 ifself.helmet:6 self.changeFrames(self.helmet_walk_frames)7 elifself.losHead:8 self.changeFrames(self.losthead_walk_frames)9 else:10 self.changeFrames(self.walk_frames)11

12 defsetAttack(self, plant):13 self.plant =plant14 self.state =c.ATTACK15 self.animate_interval = 100

16

17 ifself.helmet:18 self.changeFrames(self.helmet_attack_frames)19 elifself.losHead:20 self.changeFrames(self.losthead_attack_frames)21 else:22 self.changeFrames(self.attack_frames)23

24 defsetDie(self):25 self.state =c.DIE26 self.animate_interval = 200

27 self.changeFrames(self.die_frames)28

29 defchangeFrames(self, frames):30 '''change image frames and modify rect position'''

31 self.frames =frames32 self.frame_num =len(self.frames)33 self.frame_index =034

35 bottom =self.rect.bottom36 centerx =self.rect.centerx37 self.image =self.frames[self.frame_index]38 self.rect =self.image.get_rect()39 self.rect.bottom =bottom40 self.rect.centerx = centerx

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

1 classConeHeadZombie(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 =True5

6 defloadImages(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.name16 helmet_attack_name = self.name + 'Attack'

17 walk_name =c.NORMAL_ZOMBIE18 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 inenumerate(name_list):31 self.loadFrames(frame_list[i], name, tool.ZOMBIE_RECT[name]['x'])32

33 self.frames = self.helmet_walk_frames

学习视频关注讨论群:887934385 源码、及相关素材

编译环境

python3.7 + pygame1.9

python植物大战僵尸图片素材_Python 植物大战僵尸代码实现: 图片加载和显示切换...相关推荐

  1. python为什么import不了_python – 为什么PyImport_Import无法从当前目录加载模块?

    我正在尝试运行embedding example并且我无法从当前工作目录加载模块,除非我将其显式添加到sys.path然后它可以工作: PyRun_SimpleString("import ...

  2. python: 将多张图片生成到一个.npy文件中,加载并显示(代码)

    直接上代码,读者可根据代码注释进行理解. ```python import matplotlib.pyplot as plt import numpy as np import cv2 as cvim ...

  3. pygame显示图片的方法_pygame系列教程——1.2加载及显示图片

    前言 在上一节中,我们了解了pygame的安装及并编写了一个pygame运行的最小系统.但是,我们的游戏除了窗口就什么都没有了,未免显得过于单调了,那么本节我们就来给我们的游戏添加一些图片吧. 在讲添 ...

  4. python飞机大战游戏素材_python实现飞机大战微信小游戏

    0.前言 我学一种语言,可以说学任何东西都喜欢自己动手实践,总感觉自己动手一遍,就可以理解的更透彻,学python也一样,自己动手写代码,但更喜欢做点小东西出来,一边玩一边学.下面我就展示一下我最近做 ...

  5. Python语言学习:利用python获取当前/上级/上上级目录路径(获取路径下的最后叶目录的文件名、合并两个不同路径下图片文件名等目录/路径案例、正确加载图片路径)之详细攻略

    Python语言学习:利用python获取当前/上级/上上级目录路径(获取路径下的最后叶目录的文件名.合并两个不同路径下图片文件名等目录/路径案例.正确加载图片路径)之详细攻略 目录 利用python ...

  6. html加载完显示图片,js图片未加载完显示loading效果

    js图片未加载完显示loading效果 img{float:left;200px;height:200px;margin:0 10px 10px 0} //判断浏览器 var Browser=new ...

  7. [html] iOS下页面如何启动加载时显示画面图片?如何设置大小?它有什么好处?

    [html] iOS下页面如何启动加载时显示画面图片?如何设置大小?它有什么好处? <link rel="apple-touch-startup-image" href=&q ...

  8. Vue性能优化:图片与组件,如何实现按需加载?

    Vue性能优化:图片与组件,如何实现按需加载? 前沿:按需加载是性能优化其中的一个环节,可以是图片的按需加载,也就是lazyload来实现按需加载的场景,也可以是组件库的引入,只需部分组件的使用而无需 ...

  9. 关于图片加载的问题-如加载失败显示占位图,预加载,懒加载

    一.图片加载失败时,如图所示 <img v-if="src" :src="src" :onerror="errorImg">le ...

  10. echarts树图图标修改成图片以及自定义图片首次加载不显示的问题的修改<js>

    首先看一下显示效果,如下图所示: 1.首先修改图片,在option对象中加入 下方代码就可实现图片的修改,但是存在bug symbol:'image://https://ss2.bdstatic.co ...

最新文章

  1. myeclipse 10创建maven项目
  2. python Selenium 常见操作 元素定位
  3. XML Schema学习
  4. sklearn 分类(上证指数涨跌预测)
  5. Scala语言整理(一)
  6. UVA 10054 the necklace 欧拉回路
  7. 阿里程序员受邀去华为面试,却因这点没被录取。
  8. 2019后工作机会会更少_在2019年更多地参与和更少地命令
  9. 常用python内置函数_python常用内置函数
  10. 小故事:在缺陷中发现长处
  11. HDU 2457 DNA repair(AC自动机 + DP)题解
  12. python相机标定
  13. fineui中前端自定义函数
  14. qq音乐api android,QQ音乐
  15. [Java] Appfuse tapestry 小记
  16. golang操作elasticsearch(oliver/elastic使用文档)
  17. 微信小程序苹果手机statusBarHeight状态栏高度为0
  18. pyechars切片器如何实现
  19. 电池管理系统(BMS)功能与作用/BMS 故障分析方法/15种常见故障案例分析
  20. 无法连接数据库的一些原因和解决

热门文章

  1. java中ejb项目_创建EJB项目
  2. 微信小程序web-view组件 打开外部url
  3. 海媚服务器怎么进系统,海媚v3服务器配置
  4. OpenCore黑苹果引导配置说明-基于OpenCore-0.7.1-07-06正式版
  5. OPPO R9tm 刷机/root/救砖/第三方recovery
  6. php 注销session_php中如何删除和销毁Session
  7. 黑客是怎样买彩票的?中奖率提示2倍
  8. displaytag.properties
  9. influxdb可视化工具
  10. android移动商城源码,o2o移动社区Android端app开源源码