手把手教你用Python實現(xiàn)“坦克大戰(zhàn)”友存,(附詳細(xì)代碼5簧拧)

小時候玩的“坦克大戰(zhàn)”,你還記得嗎屡立?

今天直晨,我們使用Python以及強大的第三方庫來實現(xiàn)一個簡單的坦克大戰(zhàn)游戲搀军。

環(huán)境依賴

python3.7

pygame1.9.6

urllib

內(nèi)置庫,如random勇皇、sys罩句、time、os等

pygame介紹

Pygame被設(shè)計用來寫游戲的python模塊集合敛摘,基于SDL庫開發(fā)门烂。使用python可以導(dǎo)入pygame來開發(fā)具有全部特性的游戲和多媒體軟件,Pygame是極度輕便的并且可以運行在幾乎所有的平臺和操作系統(tǒng)上兄淫。

1. 導(dǎo)入依賴 & 通用配置

1import random

2import sys

3import time

4from urllib.request import urlretrieve

5import os

6import pygame

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# 加載圖片

2def load_img(name_img):

3 save = Tank_IMAGE_POSITION + os.sep + name_img + .gif

4 if not os.path.exists(save):

5 urlretrieve(URL + name_img + .gif , save)

6 return pygame.image.load(save)

7

8# 加載背景音樂

9def load_music(name_music):

10 save = Tank_IMAGE_POSITION + os.sep + name_music + .wav

11 if not os.path.exists(save):

12 urlretrieve(URL + name_music + .wav , save)

13 pygame.mixer.music.load(save)

14 pygame.mixer.music.play()

3. 通用基礎(chǔ)類

1

2* pygame.sprite模塊屯远,官方文檔上說這個模塊是輕量級的,在游戲開發(fā)中也未必要使用捕虽。

3* sprite翻譯為精靈慨丐,在游戲動畫一般是指一個獨立運動的畫面元素,在pygame中泄私,

4就可以是一個帶有圖像(Surface)和大小位置(Rect)的對象房揭。

5* pygame.sprite.Sprite是pygame精靈的基類,一般來說晌端,需要寫一個自己的精靈類繼承一下它然后加入自己的代碼捅暴。

6

7class BaseItem(pygame.sprite.Sprite):

8 def __init__(self):

9 super().__init__()




如果你在學(xué)習(xí)Python的過程當(dāng)中有遇見任何問題,可以加入我的python交流學(xué)企鵝群:【611+530+101】咧纠,多多交流問題蓬痒,互幫互助,群里有不錯的學(xué)習(xí)教程和開發(fā)工具惧盹。學(xué)習(xí)python有任何問題(學(xué)習(xí)方法乳幸,學(xué)習(xí)效率,如何就業(yè))钧椰,可以隨時來咨詢我


4. 定義bullet類

1class Bullet(BaseItem):

2 # 參數(shù)初始化

3 def __init__(self, tank, window):

4 super().__init__()

5 self.direction = tank.direction

6 self.speed = tank.speed * 3

7 self.img = load_img( bullet )

8 self.rect = self.img.get_rect()

9 self.window = window

10 self.live = True

11 if self.direction == U:

12 self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2

13 self.rect.top = tank.rect.top - self.rect.height

14 elif self.direction == D:

15 self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2

16 self.rect.top = tank.rect.top + tank.rect.height

17 elif self.direction == L:

18 self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2

19 self.rect.top = tank.rect.top + tank.rect.height / 2 - self.rect.height / 2

20 else:

21 self.rect.left = tank.rect.left + tank.rect.width

22 self.rect.top = tank.rect.top + tank.rect.height / 2 - self.rect.height / 2

23

24 # 子彈顯示

25 def display_bullet(self):

26 self.window.blit(self.img, self.rect)

27

28 # 通過按鍵控制子彈移動

29 def bullet_move(self):

30 if self.direction == U:

31 if self.rect.top > 0:

32 self.rect.top -= self.speed

33 return

34 elif self.direction == D:

35 if self.rect.top < SCREEN_HEIGHT:

36 self.rect.top += self.speed

37 return

38 elif self.direction == L:

39 if self.rect.left > 0:

40 self.rect.left -= self.speed

41 return

42 else:

43 if self.rect.left < SCREEN_WIDTH:

44 self.rect.left += self.speed

45 return

46 self.live = False

47

48 # 我方坦克子彈擊中對方坦克

49 def hit_enemy_tank(self):

50 for enemy in TankGame.enemy_tank_list:

51 hit = pygame.sprite.collide_rect(self, enemy)

52 if hit:

53 self.live = False

54 if enemy.click_count == 1:

55 enemy.live = False

56 return None

57 enemy.click_count -= 1

58 if enemy.click_count == 2:

59 enemy.load_image = enemy.img32

60 if enemy.click_count == 1:

61 enemy.load_image = enemy.img31

62 load_music( hit )

63

64 # 對方坦克子彈擊中我方坦克

65 def hit_my_tank(self, tank):

66 hit = pygame.sprite.collide_rect(self, tank)

67 if hit:

68 self.live = False

69 tank.live = False

70

71 # 子彈擊中圍墻

72 def bullet_collide_wall(self):

73 for wall in TankGame.wall_list:

74 result = pygame.sprite.collide_rect(self, wall)

75 if result:

76 self.live = False

77 if wall.count == 1:

78 wall.live = False

79 else:

80 load_music( hit )

81

82 # 子彈擊中子彈

83 def bullet_collide_bullet(self):

84 for bullet in TankGame.enemy_bullet_list:

85 if pygame.sprite.collide_rect(bullet, self):

86 bullet.live = False

87 self.live = False

5. 定義tank類

1class Tank(BaseItem):

2 # 參數(shù)初始化

3 def __init__(self, left, top, window, image, direction, speed):

4 super().__init__()

5 self.window = window

6 self.load_image = image

7 self.direction = direction

8 self.img = self.load_image[self.direction]

9 self.rect = self.img.get_rect()

10 self.rect.left = left

11 self.rect.top = top

12 self.speed = speed

13 self.tank_width = self.rect.width

14 self.tank_height = self.rect.height

15 self.wall_switch = False

16 self.move_stop = True

17 self.live = True

18 self.old_left = 0

19 self.old_top = 0

20

21 # 開火

22 def fire(self):

23 return Bullet(self, self.window)

24

25 # 顯示

26 def display(self):

27 self.img = self.load_image[self.direction]

28 self.window.blit(self.img, self.rect)

29

30 def wall_not(self, direction):

31 if direction == U:

32 return self.rect.top > 0

33 elif direction == D:

34 return self.rect.top <= SCREEN_HEIGHT - self.tank_height

35 elif direction == L:

36 return self.rect.left > 0

37 else:

38 return self.rect.left <= SCREEN_WIDTH - self.tank_width

39

40 def wall_yes(self, direction):

41 if direction == U:

42 if self.rect.top < 0:

43 self.rect.top = SCREEN_HEIGHT

44 elif direction == D:

45 self.rect.top %= SCREEN_HEIGHT

46 elif direction == L:

47 if self.rect.left < 0:

48 self.rect.left = SCREEN_WIDTH

49 else:

50 self.rect.left %= SCREEN_WIDTH

51

52 def move(self, direction):

53 self.old_left = self.rect.left

54 self.old_top = self.rect.top

55 if self.wall_switch:

56 self.wall_yes(direction)

57 elif not self.wall_not(direction):

58 return None

59 if direction == U:

60 self.rect.top -= self.speed

61 elif direction == D:

62 self.rect.top += self.speed

63 elif direction == L:

64 self.rect.left -= self.speed

65 else:

66 self.rect.left += self.speed

67

68 def stay(self):

69 self.rect.left = self.old_left

70 self.rect.top = self.old_top

71

72 def tank_collide_wall(self):

73 for wall in TankGame.wall_list:

74 if pygame.sprite.collide_rect(self, wall):

75 self.stay()

76

77 def tank_collide_tank(self):

78 for tank in TankGame.enemy_tank_list:

79 if pygame.sprite.collide_rect(self, tank):

80 self.stay()

6. 定義我方 & 對方tank類

1class MyTank(Tank):

2 def __init__(self, left, top, window):

3 self.img = dict(U=load_img( p2tankU ), D=load_img( p2tankD ), L=load_img( p2tankL ), R=load_img( p2tankR ))

4 self.my_tank_speed = 4

5 super().__init__(left, top, window, self.img, U, self.my_tank_speed)

6

7

8class EnemyTank(Tank):

9 def __init__(self, left, top, window):

10 self.img1 = dict(U=load_img( enemy1U ), D=load_img( enemy1D ), L=load_img( enemy1L ), R=load_img( enemy1R ))

11 self.img2 = dict(U=load_img( enemy2U ), D=load_img( enemy2D ), L=load_img( enemy2L ), R=load_img( enemy2R ))

12 self.img3 = dict(U=load_img( enemy3U ), D=load_img( enemy3D ), L=load_img( enemy3L ), R=load_img( enemy3R ))

13 self.img31 = dict(U=load_img( enemy3U_1 ), D=load_img( enemy3D_1 ), L=load_img( enemy3L_1 ),

14 R=load_img( enemy3R_1 ))

15 self.img32 = dict(U=load_img( enemy3U_2 ), D=load_img( enemy3D_2 ), L=load_img( enemy3L_2 ),

16 R=load_img( enemy3R_2 ))

17 # 不同的坦克擊中的次數(shù)不一樣

18 image, self.click_count, speed = random.choice([(self.img1, 1, 4), (self.img3, 3, 3), (self.img2, 1, 5)])

19 super().__init__(left, top, window, image, self.random_direction(), speed)

20 self.step = 100

21

22 @staticmethod

23 def random_direction():

24 n = random.randint(0, 3)

25 return DIRECTION[n]

26

27 def random_move(self):

28 if self.step == 0:

29 self.direction = self.random_direction()

30 self.step = random.randint(10, 100)

31 else:

32 self.move(self.direction)

33 self.step -= 1

34

35 def random_fire(self):

36 if random.randint(0, 50) == 1 and len(TankGame.enemy_bullet_list) < 30:

37 enemy_bullet = self.fire()

38 TankGame.enemy_bullet_list.append(enemy_bullet)

7. 爆炸動作類

1class Explode(BaseItem):

2 def __init__(self, tank, window):

3 super().__init__()

4 self.img = [load_img( blast0 ), load_img( blast1 ), load_img( blast2 ), load_img( blast3 ), load_img( blast4 ),

5 load_img( blast5 ), load_img( blast6 )]

6 self.rect = tank.rect

7 self.stop = 0

8 self.window = window

9 self.rect.left = tank.rect.left - tank.rect.width / 2

10 def display_explode(self):

11 load_music( blast )

12 while self.stop < len(self.img):

13 self.window.blit(self.img[self.stop], self.rect)

14 self.stop += 1

8. 定義wall類

1class Wall(BaseItem):

2 def __init__(self, left, top, window):

3 super().__init__()

4 self.count = random.randint(0, 1)

5 self.img = [load_img( steels ), load_img( walls )][self.count]

6 self.rect = self.img.get_rect()

7 self.rect.left = left

8 self.rect.top = top

9 self.window = window

10 self.live = True

11

12 def display_wall(self):

13 self.window.blit(self.img, self.rect)

9. 定義坦克大戰(zhàn)類

1class TankGame:

2 my_bullet_list = list()

3 enemy_bullet_list = list()

4 enemy_tank_list = list()

5 wall_list = list()

6

7 def __init__(self):

8 if not os.path.exists(Tank_IMAGE_POSITION):

9 os.makedirs(Tank_IMAGE_POSITION)

10 pygame.init()

11 pygame.font.init()

12 self.display = pygame.display

13 self.window = self.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT], pygame.RESIZABLE, 32)

14 self.display.set_caption( 坦克世界 )

15 self.my_tank = MyTank(MY_BIRTH_LEFT, MY_BIRTH_TOP, self.window)

16 self.creat_enemy_number = 10

17 self.my_tank_lift = 3

18 self.creat_enemy(self.creat_enemy_number)

19 self.creat_walls()

20 self.font = pygame.font.SysFont( kai_ti , 18)

21 self.number = 1

22

23 def creat_enemy(self, number):

24 for _ in range(number):

25 left = random.randint(0, SCREEN_WIDTH - self.my_tank.tank_width)

26 enemy_tank = EnemyTank(left, 20, self.window)

27 TankGame.enemy_tank_list.append(enemy_tank)

28

29 def creat_walls(self):

30 for i in range(SCREEN_WIDTH // 60 + 1):

31 wall_h = random.randint(100, 500)

32 w = Wall(60 * i, wall_h, self.window)

33 TankGame.wall_list.append(w)

34

35 @staticmethod

36 def show_walls():

37 for w in TankGame.wall_list:

38 if w.live:

39 w.display_wall()

40 else:

41 TankGame.wall_list.remove(w)

42

43 def start_game(self):

44 load_music( start )

45 while True:

46 self.window.fill([0, 0, 0])

47 self.get_event()

48 len_enemy = len(TankGame.enemy_tank_list)

49 self.window.blit(

50 self.draw_text( 敵方坦克*{0},我方生命值*{1},當(dāng)前{2}關(guān) .format(len_enemy, self.my_tank_lift, self.number)), (10, 10))

51 if len_enemy == 0:

52 self.creat_enemy_number += 10

53 self.number += 1

54 self.my_tank_lift += 1

55 self.creat_enemy(self.creat_enemy_number)

56 self.wall_list.clear()

57 self.creat_walls()

58 self.show_my_tank()

59 self.show_enemy_tank()

60 self.show_bullet(TankGame.enemy_bullet_list)

61 self.show_bullet(TankGame.my_bullet_list)

62 self.show_walls()

63 self.display.update()

64 time.sleep(0.02)

65

66 def show_my_tank(self):

67 if self.my_tank.live:

68 self.my_tank.display()

69 self.my_tank.tank_collide_tank()

70 self.my_tank.tank_collide_wall()

71 else:

72 Explode(self.my_tank, self.window).display_explode()

73 del self.my_tank

74 if self.my_tank_lift == 0:

75 self.end_game()

76 self.my_tank_lift -= 1

77 load_music( add )

78 self.my_tank = MyTank(MY_BIRTH_LEFT, MY_BIRTH_TOP, self.window)

79 if not self.my_tank.move_stop:

80 self.my_tank.move(self.my_tank.direction)

81

82 def show_enemy_tank(self):

83 for e in TankGame.enemy_tank_list:

84 e.random_move()

85 e.tank_collide_wall()

86 if e.live:

87 e.display()

88 else:

89 TankGame.enemy_tank_list.remove(e)

90 Explode(e, self.window).display_explode()

91 e.random_fire()

92

93 def show_bullet(self, ls):

94 for b in ls:

95 b.bullet_move()

96 b.bullet_collide_wall()

97 if ls is TankGame.my_bullet_list:

98 b.hit_enemy_tank()

99 b.bullet_collide_bullet()

100 else:

101 b.hit_my_tank(self.my_tank)

102 if b.live:

103 b.display_bullet()

104 else:

105 ls.remove(b)

106

107 def get_event(self):

108 global SCREEN_WIDTH, SCREEN_HEIGHT

109 event_list = pygame.event.get()

110 for event in event_list:

111 if event.type == pygame.VIDEORESIZE:

112 SCREEN_WIDTH, SCREEN_HEIGHT = event.size

113 self.window = self.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT], pygame.RESIZABLE, 32)

114

115 if event.type == pygame.QUIT:

116 self.end_game()

117 if event.type == pygame.KEYDOWN:

118 if event.key == pygame.K_w:

119 self.my_tank.direction = U

120 elif event.key == pygame.K_s:

121 self.my_tank.direction = D

122 elif event.key == pygame.K_a:

123 self.my_tank.direction = L

124 elif event.key == pygame.K_d:

125 self.my_tank.direction = R

126 else:

127 return None

128 self.my_tank.move_stop = False

129 elif event.type == pygame.MOUSEBUTTONDOWN:

130 if len(TankGame.my_bullet_list) < 3:

131 bullet = self.my_tank.fire()

132 load_music( fire )

133 TankGame.my_bullet_list.append(bullet)

134 elif event.type == pygame.KEYUP:

135 self.my_tank.move_stop = True

136

137 def end_game(self):

138 self.display.quit()

139 sys.exit()

140

141 def draw_text(self, content):

142 text_sf = self.font.render(content, True, [255, 0, 0])

143 return text_sf

10. 入口

1if __name__ == __main__ :

2 g = TankGame()

3 g.start_game()

執(zhí)行界面

到這兒我們的這個小游戲基本完成了哦粹断。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嫡霞,隨后出現(xiàn)的幾起案子瓶埋,更是在濱河造成了極大的恐慌,老刑警劉巖诊沪,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件养筒,死亡現(xiàn)場離奇詭異,居然都是意外死亡端姚,警方通過查閱死者的電腦和手機(jī)晕粪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渐裸,“玉大人巫湘,你說我怎么就攤上這事装悲。” “怎么了尚氛?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵诀诊,是天一觀的道長。 經(jīng)常有香客問我阅嘶,道長属瓣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任讯柔,我火速辦了婚禮抡蛙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磷杏。我一直安慰自己溜畅,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布极祸。 她就那樣靜靜地躺著,像睡著了一般怠晴。 火紅的嫁衣襯著肌膚如雪遥金。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天蒜田,我揣著相機(jī)與錄音稿械,去河邊找鬼。 笑死冲粤,一個胖子當(dāng)著我的面吹牛美莫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梯捕,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼厢呵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了傀顾?” 一聲冷哼從身側(cè)響起襟铭,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎短曾,沒想到半個月后寒砖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡嫉拐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年哩都,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婉徘。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡漠嵌,死狀恐怖咐汞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情献雅,我是刑警寧澤碉考,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站挺身,受9級特大地震影響侯谁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜章钾,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一墙贱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贱傀,春花似錦惨撇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至株搔,卻和暖如春剖淀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纤房。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工纵隔, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人炮姨。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓捌刮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舒岸。 傳聞我的和親對象是個殘疾皇子绅作,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 現(xiàn)在游戲產(chǎn)業(yè)的多種多樣,從最早的坦克大戰(zhàn)吁津、超級瑪麗到現(xiàn)在的英雄聯(lián)盟棚蓄、刺激戰(zhàn)場等等數(shù)不勝數(shù),你還記得最早的飛機(jī)大戰(zhàn)嗎...
    小猿圈IT教育閱讀 953評論 0 1
  • 這次呢碍脏,讓我們重溫一下兒時的樂趣梭依,用Python做一個飛機(jī)大戰(zhàn)的小游戲。接下來典尾,讓我們一起走進(jìn)“飛機(jī)大戰(zhàn)”役拴。 一....
    HDhandi閱讀 1,910評論 1 4
  • 大家好。小編通過這段時間學(xué)習(xí)做了一個超級簡單的打飛機(jī)〖毓。現(xiàn)在貢獻(xiàn)給大家河闰。 我們先要建兩個.py文件科平。小編在這里是建的...
    AnHuaFeng閱讀 5,281評論 0 0
  • 具體的代碼: settings配置 import pygame class Settings(object): ...
    ae0fdc75017d閱讀 189評論 0 1
  • 參加早起營1個月,給自己定的計劃是6點起床姜性,6點半前洗漱準(zhǔn)備早餐瞪慧,6點半-7點半學(xué)習(xí),7點半出門上班部念。 第一周 揣...
    FeliaLee閱讀 307評論 2 1