小時候玩的“坦克大戰(zhàn)”,你還記得嗎?
滿滿的回憶
!
今天,我們使用Python以及強大的第三方庫來實現(xiàn)一個簡單的坦克大戰(zhàn)游戲。
整體效果
環(huán)境依賴
python3.7
pygame1.9.6
urllib
內置庫,如random、sys、time、os等
pygame介紹
Pygame被設計用來寫游戲的python模塊集合,基于SDL庫開發(fā)。使用python可以導入pygame來開發(fā)具有全部特性的游戲和多媒體軟件,Pygame是極度輕便的并且可以運行在幾乎所有的平臺和操作系統(tǒng)上。
1. 導入依賴 & 通用配置
1importrandom
2importsys
3importtime
4fromurllib.requestimporturlretrieve
5importos
6importpygame
7
8
9SCREEN_WIDTH,?SCREEN_HEIGHT?=1200,700#?畫面大小
10MY_BIRTH_LEFT,?MY_BIRTH_TOP?=?SCREEN_WIDTH?/2,?SCREEN_HEIGHT?-60
11DIRECTION?=?[U,?D,?L,?R]?=?[ U , D , L , R ]#?控制鍵
12Tank_IMAGE_POSITION?=r D:/tank_img
13URL?= https://gitee.com/tyoui/logo/raw/master/img/
?2. 通用加載函數(shù)
1#?加載圖片
2defload_img(name_img):
3save?=?Tank_IMAGE_POSITION?+?os.sep?+?name_img?+ .gif
4ifnotos.path.exists(save):
5urlretrieve(URL?+?name_img?+ .gif ,?save)
6returnpygame.image.load(save)
7
8#?加載背景音樂
9defload_music(name_music):
10save?=?Tank_IMAGE_POSITION?+?os.sep?+?name_music?+ .wav
11ifnotos.path.exists(save):
12urlretrieve(URL?+?name_music?+ .wav ,?save)
13pygame.mixer.music.load(save)
14pygame.mixer.music.play()
3. 通用基礎類
1
2* pygame.sprite模塊,官方文檔上說這個模塊是輕量級的,在游戲開發(fā)中也未必要使用。
3*?sprite翻譯為精靈,在游戲動畫一般是指一個獨立運動的畫面元素,在pygame中,
4就可以是一個帶有圖像(Surface)和大小位置(Rect)的對象。
5* pygame.sprite.Sprite是pygame精靈的基類,一般來說,需要寫一個自己的精靈類繼承一下它然后加入自己的代碼。
6
7classBaseItem(pygame.sprite.Sprite):
8def__init__(self):
9super().__init__()
4. 定義bullet類
1classBullet(BaseItem):
2#?參數(shù)初始化
3def__init__(self,?tank,?window):
4super().__init__()
5self.direction?=?tank.direction
6self.speed?=?tank.speed?*3
7self.img?=?load_img( bullet )
8self.rect?=?self.img.get_rect()
9self.window?=?window
10self.live?=True
11ifself.direction?==?U:
12self.rect.left?=?tank.rect.left?+?tank.rect.width?/2-?self.rect.width?/2
13self.rect.top?=?tank.rect.top?-?self.rect.height
14elifself.direction?==?D:
15self.rect.left?=?tank.rect.left?+?tank.rect.width?/2-?self.rect.width?/2
16self.rect.top?=?tank.rect.top?+?tank.rect.height
17elifself.direction?==?L:
18self.rect.left?=?tank.rect.left?-?self.rect.width?/2-?self.rect.width?/2
19self.rect.top?=?tank.rect.top?+?tank.rect.height?/2-?self.rect.height?/2
20else:
21self.rect.left?=?tank.rect.left?+?tank.rect.width
22self.rect.top?=?tank.rect.top?+?tank.rect.height?/2-?self.rect.height?/2
23
24#?子彈顯示
25defdisplay_bullet(self):
26self.window.blit(self.img,?self.rect)
27
28#?通過按鍵控制子彈移動
29defbullet_move(self):
30ifself.direction?==?U:
31ifself.rect.top?>0:
32self.rect.top?-=?self.speed
33return
34elifself.direction?==?D:
35ifself.rect.top?<?SCREEN_HEIGHT:
36self.rect.top?+=?self.speed
37return
38elifself.direction?==?L:
39ifself.rect.left?>0:
40self.rect.left?-=?self.speed
41return
42else:
43ifself.rect.left?<?SCREEN_WIDTH:
44self.rect.left?+=?self.speed
45return
46self.live?=False
47
48#?我方坦克子彈擊中對方坦克
49defhit_enemy_tank(self):
50forenemyinTankGame.enemy_tank_list:
51hit?=?pygame.sprite.collide_rect(self,?enemy)
52ifhit:
53self.live?=False
54ifenemy.click_count?==1:
55enemy.live?=False
56returnNone
57enemy.click_count?-=1
58ifenemy.click_count?==2:
59enemy.load_image?=?enemy.img32
60ifenemy.click_count?==1:
61enemy.load_image?=?enemy.img31
62load_music( hit )
63
64#?對方坦克子彈擊中我方坦克
65defhit_my_tank(self,?tank):
66hit?=?pygame.sprite.collide_rect(self,?tank)
67ifhit:
68self.live?=False
69tank.live?=False
70
71#?子彈擊中圍墻
72defbullet_collide_wall(self):
73forwallinTankGame.wall_list:
74result?=?pygame.sprite.collide_rect(self,?wall)
75ifresult:
76self.live?=False
77ifwall.count?==1:
78wall.live?=False
79else:
80load_music( hit )
81
82#?子彈擊中子彈
83defbullet_collide_bullet(self):
84forbulletinTankGame.enemy_bullet_list:
85ifpygame.sprite.collide_rect(bullet,?self):
86bullet.live?=False
87self.live?=False
5. 定義tank類
1classTank(BaseItem):
2#?參數(shù)初始化
3def__init__(self,?left,?top,?window,?image,?direction,?speed):
4super().__init__()
5self.window?=?window
6self.load_image?=?image
7self.direction?=?direction
8self.img?=?self.load_image[self.direction]
9self.rect?=?self.img.get_rect()
10self.rect.left?=?left
11self.rect.top?=?top
12self.speed?=?speed
13self.tank_width?=?self.rect.width
14self.tank_height?=?self.rect.height
15self.wall_switch?=False
16self.move_stop?=True
17self.live?=True
18self.old_left?=0
19self.old_top?=0
20
21#?開火
22deffire(self):
23returnBullet(self,?self.window)
24
25#?顯示
26defdisplay(self):
27self.img?=?self.load_image[self.direction]
28self.window.blit(self.img,?self.rect)
29
30defwall_not(self,?direction):
31ifdirection?==?U:
32returnself.rect.top?>0
33elifdirection?==?D:
34returnself.rect.top?<=?SCREEN_HEIGHT?-?self.tank_height
35elifdirection?==?L:
36returnself.rect.left?>0
37else:
38returnself.rect.left?<=?SCREEN_WIDTH?-?self.tank_width
39
40defwall_yes(self,?direction):
41ifdirection?==?U:
42ifself.rect.top?<0:
43self.rect.top?=?SCREEN_HEIGHT
44elifdirection?==?D:
45self.rect.top?%=?SCREEN_HEIGHT
46elifdirection?==?L:
47ifself.rect.left?<0:
48self.rect.left?=?SCREEN_WIDTH
49else:
50self.rect.left?%=?SCREEN_WIDTH
51
52defmove(self,?direction):
53self.old_left?=?self.rect.left
54self.old_top?=?self.rect.top
55ifself.wall_switch:
56self.wall_yes(direction)
57elifnotself.wall_not(direction):
58returnNone
59ifdirection?==?U:
60self.rect.top?-=?self.speed
61elifdirection?==?D:
62self.rect.top?+=?self.speed
63elifdirection?==?L:
64self.rect.left?-=?self.speed
65else:
66self.rect.left?+=?self.speed
67
68defstay(self):
69self.rect.left?=?self.old_left
70self.rect.top?=?self.old_top
71
72deftank_collide_wall(self):
73forwallinTankGame.wall_list:
74ifpygame.sprite.collide_rect(self,?wall):
75self.stay()
76
77deftank_collide_tank(self):
78fortankinTankGame.enemy_tank_list:
79ifpygame.sprite.collide_rect(self,?tank):
80self.stay()
6. 定義我方 & 對方tank類
1classMyTank(Tank):
2def__init__(self,?left,?top,?window):
3self.img?=?dict(U=load_img( p2tankU ),?D=load_img( p2tankD ),?L=load_img( p2tankL ),?R=load_img( p2tankR ))
4self.my_tank_speed?=4
5super().__init__(left,?top,?window,?self.img,?U,?self.my_tank_speed)
6
7
8classEnemyTank(Tank):
9def__init__(self,?left,?top,?window):
10self.img1?=?dict(U=load_img( enemy1U ),?D=load_img( enemy1D ),?L=load_img( enemy1L ),?R=load_img( enemy1R ))
11self.img2?=?dict(U=load_img( enemy2U ),?D=load_img( enemy2D ),?L=load_img( enemy2L ),?R=load_img( enemy2R ))
12self.img3?=?dict(U=load_img( enemy3U ),?D=load_img( enemy3D ),?L=load_img( enemy3L ),?R=load_img( enemy3R ))
13self.img31?=?dict(U=load_img( enemy3U_1 ),?D=load_img( enemy3D_1 ),?L=load_img( enemy3L_1 ),
14R=load_img( enemy3R_1 ))
15self.img32?=?dict(U=load_img( enemy3U_2 ),?D=load_img( enemy3D_2 ),?L=load_img( enemy3L_2 ),
16R=load_img( enemy3R_2 ))
17#?不同的坦克擊中的次數(shù)不一樣
18image,?self.click_count,?speed?=?random.choice([(self.img1,1,4),?(self.img3,3,3),?(self.img2,1,5)])
19super().__init__(left,?top,?window,?image,?self.random_direction(),?speed)
20self.step?=100
21
22@staticmethod
23defrandom_direction():
24n?=?random.randint(0,3)
25returnDIRECTION[n]
26
27defrandom_move(self):
28ifself.step?==0:
29self.direction?=?self.random_direction()
30self.step?=?random.randint(10,100)
31else:
32self.move(self.direction)
33self.step?-=1
34
35defrandom_fire(self):
36ifrandom.randint(0,50)?==1andlen(TankGame.enemy_bullet_list)?<30:
37enemy_bullet?=?self.fire()
38TankGame.enemy_bullet_list.append(enemy_bullet)
7. 爆炸動作類
1classExplode(BaseItem):
2def__init__(self,?tank,?window):
3super().__init__()
4self.img?=?[load_img( blast0 ),?load_img( blast1 ),?load_img( blast2 ),?load_img( blast3 ),?load_img( blast4 ),
5load_img( blast5 ),?load_img( blast6 )]
6self.rect?=?tank.rect
7self.stop?=0
8self.window?=?window
9self.rect.left?=?tank.rect.left?-?tank.rect.width?/2
10defdisplay_explode(self):
11load_music( blast )
12whileself.stop?<?len(self.img):
13self.window.blit(self.img[self.stop],?self.rect)
14self.stop?+=1
8. 定義wall類
1classWall(BaseItem):
2def__init__(self,?left,?top,?window):
3super().__init__()
4self.count?=?random.randint(0,1)
5self.img?=?[load_img( steels ),?load_img( walls )][self.count]
6self.rect?=?self.img.get_rect()
7self.rect.left?=?left
8self.rect.top?=?top
9self.window?=?window
10self.live?=True
11
12defdisplay_wall(self):
13self.window.blit(self.img,?self.rect)
9. 定義坦克大戰(zhàn)類
? 1classTankGame:
? 2my_bullet_list?=?list()
? 3enemy_bullet_list?=?list()
? 4enemy_tank_list?=?list()
? 5wall_list?=?list()
? 6
? 7def__init__(self):
? 8ifnotos.path.exists(Tank_IMAGE_POSITION):
? 9os.makedirs(Tank_IMAGE_POSITION)
10pygame.init()
11pygame.font.init()
12self.display?=?pygame.display
13self.window?=?self.display.set_mode([SCREEN_WIDTH,?SCREEN_HEIGHT],?pygame.RESIZABLE,32)
14self.display.set_caption( 坦克世界 )
15self.my_tank?=?MyTank(MY_BIRTH_LEFT,?MY_BIRTH_TOP,?self.window)
16self.creat_enemy_number?=10
17self.my_tank_lift?=3
18self.creat_enemy(self.creat_enemy_number)
19self.creat_walls()
20self.font?=?pygame.font.SysFont( kai_ti ,18)
21self.number?=1
22
23defcreat_enemy(self,?number):
24for_inrange(number):
25left?=?random.randint(0,?SCREEN_WIDTH?-?self.my_tank.tank_width)
26enemy_tank?=?EnemyTank(left,20,?self.window)
27TankGame.enemy_tank_list.append(enemy_tank)
28
29defcreat_walls(self):
30foriinrange(SCREEN_WIDTH?//60+1):
31wall_h?=?random.randint(100,500)
32w?=?Wall(60*?i,?wall_h,?self.window)
33TankGame.wall_list.append(w)
34
35@staticmethod
36defshow_walls():
37forwinTankGame.wall_list:
38ifw.live:
39w.display_wall()
40else:
41TankGame.wall_list.remove(w)
42
43defstart_game(self):
44load_music( start )
45whileTrue:
46self.window.fill([0,0,0])
47self.get_event()
48len_enemy?=?len(TankGame.enemy_tank_list)
49self.window.blit(
50self.draw_text( 敵方坦克*{0},我方生命值*{1},當前{2}關 .format(len_enemy,?self.my_tank_lift,?self.number)),?(10,10))
51iflen_enemy?==0:
52self.creat_enemy_number?+=10
53self.number?+=1
54self.my_tank_lift?+=1
55self.creat_enemy(self.creat_enemy_number)
56self.wall_list.clear()
57self.creat_walls()
58self.show_my_tank()
59self.show_enemy_tank()
60self.show_bullet(TankGame.enemy_bullet_list)
61self.show_bullet(TankGame.my_bullet_list)
62self.show_walls()
63self.display.update()
64time.sleep(0.02)
65
66defshow_my_tank(self):
67ifself.my_tank.live:
68self.my_tank.display()
69self.my_tank.tank_collide_tank()
70self.my_tank.tank_collide_wall()
71else:
72Explode(self.my_tank,?self.window).display_explode()
73delself.my_tank
74ifself.my_tank_lift?==0:
75self.end_game()
76self.my_tank_lift?-=1
77load_music( add )
78self.my_tank?=?MyTank(MY_BIRTH_LEFT,?MY_BIRTH_TOP,?self.window)
79ifnotself.my_tank.move_stop:
80self.my_tank.move(self.my_tank.direction)
81
82defshow_enemy_tank(self):
83foreinTankGame.enemy_tank_list:
84e.random_move()
85e.tank_collide_wall()
86ife.live:
87e.display()
88else:
89TankGame.enemy_tank_list.remove(e)
90Explode(e,?self.window).display_explode()
91e.random_fire()
92
93defshow_bullet(self,?ls):
94forbinls:
95b.bullet_move()
96b.bullet_collide_wall()
97iflsisTankGame.my_bullet_list:
98b.hit_enemy_tank()
99b.bullet_collide_bullet()
100else:
101b.hit_my_tank(self.my_tank)
102ifb.live:
103b.display_bullet()
104else:
105ls.remove(b)
106
107defget_event(self):
108globalSCREEN_WIDTH,?SCREEN_HEIGHT
109event_list?=?pygame.event.get()
110foreventinevent_list:
111ifevent.type?==?pygame.VIDEORESIZE:
112SCREEN_WIDTH,?SCREEN_HEIGHT?=?event.size
113self.window?=?self.display.set_mode([SCREEN_WIDTH,?SCREEN_HEIGHT],?pygame.RESIZABLE,32)
114
115ifevent.type?==?pygame.QUIT:
116self.end_game()
117ifevent.type?==?pygame.KEYDOWN:
118ifevent.key?==?pygame.K_w:
119self.my_tank.direction?=?U
120elifevent.key?==?pygame.K_s:
121self.my_tank.direction?=?D
122elifevent.key?==?pygame.K_a:
123self.my_tank.direction?=?L
124elifevent.key?==?pygame.K_d:
125self.my_tank.direction?=?R
126else:
127returnNone
128self.my_tank.move_stop?=False
129elifevent.type?==?pygame.MOUSEBUTTONDOWN:
130iflen(TankGame.my_bullet_list)?<3:
131bullet?=?self.my_tank.fire()
132load_music( fire )
133TankGame.my_bullet_list.append(bullet)
134elifevent.type?==?pygame.KEYUP:
135self.my_tank.move_stop?=True
136
137defend_game(self):
138self.display.quit()
139sys.exit()
140
141defdraw_text(self,?content):
142text_sf?=?self.font.render(content,True,?[255,0,0])
143returntext_sf
10. 入口
1if__name__?== __main__ :
2g?=?TankGame()
3g.start_game()
執(zhí)行界面