游戲介紹
以前很火的植物大戰僵尸游戲, 本想在網上找個python版本游戲學習下,無奈沒有發現比較完整的,那就自己來寫一個把,圖片資源是從github上下載的,因為圖片資源有限,只能實作幾種植物和僵尸,功能實作如下:
支持的植物型別:太陽花,豌豆射手,寒冰射手,堅果,櫻桃炸彈,新增加植物:雙重豌豆射手,三重豌豆射手,
支持的僵尸型別:普通僵尸,棋子僵尸,路障僵尸,鐵桶僵尸,
使用json檔案保存關卡資訊,設定僵尸出現的時間和位置,
新增加除草機,
下面是游戲的截圖:
另外大家要注意:不管你是為了Python就業還是興趣愛好,記住:專案開發經驗永遠是核心,如果你沒有2020最新python入門到高級實戰視頻教程,可以去小編的Python交流.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,里面很多新python教程專案,還可以跟老司機交流討教!
圖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 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 update(self, game_info):
2 self.current_time = game_info[c.CURRENT_TIME]
3 self.handleState()
4 self.animation()
5
6 def handleState(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 def animation(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 = 0
22 self.animate_timer = self.current_time
23
24 self.image = self.frames[self.frame_index]復制代碼
下面四個函式是修改僵尸的當前狀態和圖片顯示,
- 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就業還是興趣愛好,記住:專案開發經驗永遠是核心,如果你沒有2020最新python入門到高級實戰視頻教程,可以去小編的Python交流.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,里面很多新python教程專案,還可以跟老司機交流討教!
本文的文字及圖片來源于網路加上自己的想法,僅供學習、交流使用,不具有任何商業用途,著作權歸原作者所有,如有問題請及時聯系我們以作處理,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/150256.html
標籤:Python
上一篇:Flask-基本使用
