Introduction to the game
The functions are as follows:
Supported plant types: sunflower, pea shooter, ice shooter, nut, cherry bomb. New plants: Double pea shooter, triple pea shooter.
Supported zombie types: ordinary zombie, chess zombie, roadblock zombie, bucket zombie.
Use the json file to save the level information and set the time and location of zombies.
New lawn mower.
Here is a screenshot of the game:
In addition, you should pay attention to: whether you are for Python employment or hobbies, remember: project development experience is always the core. If you don't have the latest Python introduction to advanced practical video tutorials in 2020, you can go to the small Python exchange : you can find a lot of new Python tutorial projects under the transformation of "seven clothes, nine seven buses and five numbers" (homophony of numbers). You can also communicate with the old driver for advice!
Figure 2
Picture display switch
As can be seen from Figure 1 and Figure 2, the image display of zombies will be different when they walk and attack. This article will talk about how to switch the image display.
Take the roadblock zombies above as an example. There are several types of pictures below.
- Walking with barricades
- Attack with roadblocks
- Walking without barricades (i.e. turning into ordinary zombie walking)
- Attacks without roadblocks (i.e. attacks that become normal zombies)
- Walking without head
- Headless attack
- death
Figure 3 is an example of these seven image types of roadblock zombies
Picture loading
The picture resources of zombies in plant wars are quite special. Each action of a picture type is a separate picture, as shown in Figure 4, the action picture of zombies attacking with roadblocks, with a total of 11 pictures, so the code to load the pictures should be modified accordingly.
Full code
github link of game implementation code Plants V.S. Zombies
Here is the download link of csdn Plants V.S. Zombies
Picture loading
In source\tool.py, the load? All? Gfx function traverses the resources\graphics directory and subdirectories.
A simple distinction is made in the code:
- If it is a picture in the resources\graphics\subfolder \ directory, it is a separate picture, such as the interface picture in the resources\graphics\Screen directory
- If it is a subdirectory in the resources\graphics\subfolder \ directory, all the pictures in this subdirectory or subdirectory belong to one picture type. For example, in the resources\graphics\Zombies\ConeheadZombie\ConeheadZombieAttack directory, there are action pictures of roadblock zombie attacking with roadblock, as shown in Figure 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"))Copy code
The load image frames function saves all the pictures in the directory in the tmp dictionary according to the index value in the picture name as key. For example, if the image name is "coneheadzombieatack_", its index value is 2.
Then add the image to the frame list according to the index value.
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_listCopy code
Picture display switch
In source\component\zombie.py, Zombie class is the parent class of all Zombie classes. The initialization function calls loadImages function to load all supported image types, and sets Sprite sprite class to display the required member variables image and rect.
The loadFrames function is called to specific subclasses to get pictures.
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))Copy code
The basic functions are implemented in the Zombie parent class. If the child class has special requirements, the function with the same name can be redefined.
Update function: each tick will call the entry function to update the location of zombies, switch status and update the image display.
handleState function: performs different functions based on the current state of the zombie.
Animation function: displays the next action of the picture type every specified animation interval time.
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]Copy code
The following four functions are to modify the current status and image display of zombies.
- setWalk function: change to walking state, the picture display will set different picture types according to different values.
- setAttack function: modify to attack state, and the picture display will set different picture types according to different values.
- setDie function: change to dead state.
- changeFrames function: after modifying the picture type, you need to reset the values of the member variables frame_num, frame_index, image and 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 = centerxCopy code
The roadblock zombie class is relatively simple. You only need to implement the loadImages function and call the loadFrames function to load the image types supported by the zombie. The main difference here is that the names of different types of zombies will be different.
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
This is the Python code. Note: whether you are for Python employment or hobbies, remember: project development experience is always the core. If you don't have the latest Python introduction to the advanced practical video tutorial in 2020, you can go to the small Python exchange : you can find a lot of new Python tutorial projects under the transformation of "seven clothes, nine seven buses and five numbers" (homophony of numbers). You can also exchange and consult with the old drivers!
The text and pictures of this article come from the Internet and my own ideas. They are only for learning and communication. They have no commercial use. The copyright belongs to the original author. If you have any questions, please contact us in time for handling.