python之游戲開發-坦克大戰


  1   #! /usr/bin/env python
  2 # -*- coding:utf8 -*-
  3 '''
  4 *author:wasua
  5 *purpose:學習python語言,其中的類以及pygame應用
  6 *date:2019/04/20
  7 '''
  8 
  9 '''
 10 類:
 11     sprite:
 12         1.游戲主界面
 13 
 14         2.坦克:我方坦克\敵方坦克
 15             1.移動
 16             2.發射炮彈
 17         3.炮彈:大炮彈\小炮彈
 18             1.撞到
 19             2.爆炸(也是一個連續圖片)
 20         4.障礙物:
 21        1.能否闖過
 22        2.能否擊毀
 23 
 24         5.爆炸
 25 
 26 '''
 27 
 28 import pygame, sys, time
 29 from random import randint
 30 
 31 
 32 class TankMain(object):
 33     """坦克大戰的主窗口"""
 34     Width = 1000
 35     Height = 800
 36     live_count = 4  # 3次復活機會
 37     my_tank = None
 38     #steel_wall = []
 39     #block_wall = []
 40     #grass_wall = []
 41     wall=[]
 42     my_tank_missile = []
 43     enemy_list = pygame.sprite.Group()
 44     enemy_missile_list = pygame.sprite.Group()
 45     explode_list = []
 46 
 47     # 開始游戲的方法
 48     def startGame(self):
 49         pygame.init()
 50         # 創建一個平面,設置平面大小(寬,高),窗口的屬性(0,RESIZEBLE,FULLSCREEN)
 51         screem = pygame.display.set_mode((TankMain.Width, TankMain.Height), 0, 32)
 52         # 設置窗口標題
 53         pygame.display.set_caption('坦克大戰')
 54         for i in range(6):#此處應該編寫一個函數來進行比較好
 55             TankMain.wall.append(SteelsWall(screem, 100 + i * 60, 100))
 56             TankMain.wall.append(BlockWall(screem, 700, 100 + i * 60))
 57             TankMain.wall.append(GrassWall(screem, 500, 0 + i * 60))
 58             TankMain.wall.append(GrassWall(screem,50,40))
 59 
 60         #wall = TankMain.steel_wall + TankMain.grass_wall + TankMain.block_wall
 61         TankMain.my_tank = My_TanK(screem)
 62         for i in range(0, 20):
 63             TankMain.enemy_list.add(Enemy_TanK(screem))
 64         while True:
 65             # if len(TankMain.enemy_list)<5:#地獄模式
 66             #    TankMain.enemy_list.add(Enemy_TanK(screem))
 67             # 顯示牆
 68             for i in TankMain.wall:
 69                 i.display()
 70                 i.hit_tank()
 71                 i.hit_missile()
 72                 if not i.live:
 73                     TankMain.wall.remove(i)
 74                 pygame.display.update()  # 此處不添加則會導致圖片不顯示
 75             # 設置窗口填充(背景---RGB模式)
 76             screem.fill((0, 0, 0))
 77             # 顯示左上角的文字
 78             for index, text in enumerate(self.write_text(TankMain.enemy_list)):
 79                 screem.blit(text, (0, 5 + (15 * index)))
 80             # screem.blit(self.write_text(TankMain.enemy_list),(0,0))
 81             self.get_event(TankMain.my_tank, screem)
 82             if TankMain.my_tank:
 83                 TankMain.my_tank.hit_enemy_missile()
 84             if TankMain.my_tank and TankMain.my_tank.live:
 85                 TankMain.my_tank.display()
 86                 TankMain.my_tank.move()
 87             else:
 88                 TankMain.my_tank = None
 89             for enemy in TankMain.enemy_list:
 90                 enemy.display()
 91                 enemy.random_move()
 92                 enemy.random_fire()
 93             for m in TankMain.my_tank_missile:
 94                 if m.live:
 95                     m.display()
 96                     m.hit_tank()
 97                     m.move()
 98                 else:
 99                     TankMain.my_tank_missile.remove(m)
100 
101             for m in TankMain.enemy_missile_list:
102                 if m.live:
103                     m.display()
104                     m.move()
105                 else:
106                     TankMain.enemy_missile_list.remove(m)
107 
108             for explode in TankMain.explode_list:
109                 explode.display()
110             # 顯示重置
111             time.sleep(0.1)
112             pygame.display.update()
113 
114     # 關閉游戲
115     def stopGame(self):
116         sys.exit()
117 
118     # 屏幕左上角顯示文字內容
119     def write_text(self, enemy_list):
120         # 定義字體
121         font = pygame.font.SysFont('微軟雅黑', 15, (255, 255, 255))
122         # 根據字體創建一個文件圖像
123         text_sf1 = font.render(u'敵方坦克數量為:%d' % len(enemy_list), True, (255, 255, 255))
124         text_sf2 = font.render(u'生命數量:%d' % (int(TankMain.live_count) - 1), True, (255, 255, 255))
125         return text_sf1, text_sf2
126 
127     # 獲取事件,敲擊鍵盤,鼠標點擊
128     def get_event(self, my_tank, screem):
129         for event in pygame.event.get():
130             if event.type == pygame.QUIT:  # 我方坦克犧牲后不能按Esc恩退出
131                 self.stopGame()
132             if event.type == pygame.KEYDOWN and (not TankMain.my_tank) and (
133                     event.key == pygame.K_r or event.key == pygame.K_n):  # 按n或r復活
134                 TankMain.my_tank = My_TanK(screem)  # 我方坦克不復活不可以按Esc退出
135                 TankMain.live_count -= 1
136                 if TankMain.live_count == 0:
137                     sys.exit()
138             if event.type == pygame.KEYDOWN and my_tank:
139                 if event.key == pygame.K_LEFT or event.key == pygame.K_a:
140                     my_tank.direction = "L"
141                     my_tank.stop = False
142                 if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
143                     my_tank.direction = "R"
144                     my_tank.stop = False
145                 if event.key == pygame.K_UP or event.key == pygame.K_w:
146                     my_tank.direction = 'U'
147                     my_tank.stop = False
148                 if event.key == pygame.K_DOWN or event.key == pygame.K_x:
149                     my_tank.direction = "D"
150                     my_tank.stop = False
151                 if event.key == pygame.K_ESCAPE:
152                     self.stopGame()
153                 if event.key == pygame.K_SPACE:
154                     m = my_tank.fire()
155                     m.good = True
156                     TankMain.my_tank_missile.append(m)
157             if event.type == pygame.K_UP:
158                 if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_a or event.key == pygame.K_d or event.key == pygame.K_w or event.key == pygame.K_x:
159                     my_tank.stop = True
160             if event.type == pygame.MOUSEMOTION:
161                 pass
162 
163 
164 # 坦克大戰中所有對象的父類
165 class BaseItem(pygame.sprite.Sprite):
166     def __init__(self, screem):
167         pygame.sprite.Sprite.__init__(self)
168         self.screem = screem
169 
170     def display(self):
171         if self.live:
172             self.image = self.images[self.direction]
173             self.screem.blit(self.image, self.rect)
174 
175 
176 # 坦克類
177 class Tank(BaseItem):
178     Width = 48
179     Height = 48
180 
181     def __init__(self, screem, left, top):
182         super().__init__(screem)
183         self.screem = screem
184         self.direction = "D"  # 坦克默認方向向下(上下左右)
185         self.speed = 5  # 坦克移動速度
186         self.stop = False
187         self.images = {}  # 坦克圖集
188         self.images['L'] = pygame.image.load('image/enemytank/tankl.png')
189         self.images['R'] = pygame.image.load('image/enemytank/tankr.png')
190         self.images['U'] = pygame.image.load('image/enemytank/tanku.png')
191         self.images['D'] = pygame.image.load('image/enemytank/tankd.png')
192         self.image = self.images[self.direction]
193         self.rect = self.image.get_rect()
194         self.rect.left = left
195         self.rect.top = top
196         self.live = True  # 覺得坦克是否存活
197         self.oldtop = self.rect.top
198         self.oldleft = self.rect.left
199     # 將坦克對相應圖片顯示在游戲窗口
200     def stay(self):
201         self.rect.left = self.oldleft
202         self.rect.top = self.oldtop
203     def move(self):
204         if not self.stop:
205             self.oldtop = self.rect.left
206             self.oldleft = self.rect.top
207             if self.direction == "L":
208                 if self.rect.left > 0:  # 坦克是否到達左邊界
209                     self.rect.left -= self.speed
210                 else:
211                     self.rect.left = 0
212             elif self.direction == "R":
213                 if self.rect.right < TankMain.Width:
214                     self.rect.right += self.speed
215                 else:
216                     self.rect.right = TankMain.Width
217             elif self.direction == "U":
218                 if self.rect.top > 0:
219                     self.rect.top -= self.speed
220                 else:
221                     self.rect.top = 0
222             elif self.direction == "D":
223                 if self.rect.top < TankMain.Height:
224                     self.rect.top += self.speed
225                 else:
226                     self.rect.top = TankMain.Height
227             else:
228                 pass
229     def fire(self):
230         m = Missile(self.screem, self)
231         return m
232 
233 
234 class My_TanK(Tank):
235     def __init__(self, screem):
236         super().__init__(screem, 275, 450)
237         self.images = {}  # 坦克圖集
238         self.images['L'] = pygame.image.load('image/my_tank/mytankl.png')
239         self.images['R'] = pygame.image.load('image/my_tank/mytankr.png')
240         self.images['U'] = pygame.image.load('image/my_tank/mytanku.png')
241         self.images['D'] = pygame.image.load('image/my_tank/mytankd.png')
242         self.image = self.images[self.direction]
243         self.rect = self.image.get_rect()
244 
245     def hit_enemy_missile(self):
246         hit_list = pygame.sprite.spritecollide(self, TankMain.enemy_missile_list, True)
247         for m in hit_list:  # 我方坦克中彈
248             m.live = False
249             TankMain.enemy_missile_list.remove(m)
250             self.live = False
251             explode = Explode(self.screem, self.rect)
252             TankMain.explode_list.append(explode)
253 
254 
255 class Enemy_TanK(Tank):
256     def __init__(self, screem):
257         super().__init__(screem, randint(0, TankMain.Height), randint(0, TankMain.Width))
258         self.step = randint(5, 10)
259         self.get_random_direction()
260     def get_random_direction(self):
261         r = randint(0, 4)
262         if r == 0:
263             self.stop = True
264         elif r == 1:
265             self.direction = 'L'
266             self.stop = False
267         elif r == 2:
268             self.direction = 'R'
269             self.stop = False
270         elif r == 3:
271             self.direction = 'U'
272             self.stop = False
273         elif r == 4:
274             self.direction = 'D'
275             self.stop = False
276         else:
277             pass
278     # 敵方坦克按隨機方向連續移動多步才改變方向
279     def random_move(self):
280         if self.live:
281             if self.step == 0:
282                 self.get_random_direction()
283                 self.step = randint(5, 10)
284             else:
285                 self.move()
286                 self.step -= 1
287     def random_fire(self):
288         r = randint(0, 50)
289         if r > 45:
290             m = self.fire()
291             TankMain.enemy_missile_list.add(m)
292         else:
293             return
294 
295 
296 class Missile(BaseItem):
297     Width = 8
298     Height = 8
299     def __init__(self, screem, tank):
300         # super().__init__(screem)坑
301         # print('error')
302         super().__init__(screem)
303         self.screem = screem
304         self.tank = tank
305         self.direction = tank.direction  # 炮彈方向隨坦克默認方向向下(上下左右)
306         self.speed = 60  # 炮彈移動速度
307         self.stop = False
308         self.images = {}  # 坦克圖集
309         self.images['L'] = pygame.image.load('image/missile/missile.png')
310         self.images['R'] = pygame.image.load('image/missile/missile.png')
311         self.images['U'] = pygame.image.load('image/missile/missile.png')
312         self.images['D'] = pygame.image.load('image/missile/missile.png')
313         self.image = self.images[self.direction]
314         self.rect = self.image.get_rect()
315         self.rect.left = tank.rect.left + (tank.Width - self.Width) / 2
316         self.rect.top = tank.rect.top + (tank.Height - self.Height) / 2
317         self.live = True  # 決定炮彈是否存在
318         self.good = False
319     def move(self):
320         if self.live:
321             if self.direction == "L":
322                 if self.rect.left > 0:  # 坦克是否到達左邊界
323                     self.rect.left -= self.speed
324                 else:
325                     self.live = False
326             elif self.direction == "R":
327                 if self.rect.right < TankMain.Width:
328                     self.rect.right += self.speed
329                 else:
330                     self.live = False
331             elif self.direction == "U":
332                 if self.rect.top > 0:
333                     self.rect.top -= self.speed
334                 else:
335                     self.live = False
336             elif self.direction == "D":
337                 if self.rect.top < TankMain.Height:
338                     self.rect.top += self.speed
339                 else:
340                     self.live = False
341             else:
342                 pass
343     # 炮彈擊中坦克:我擊中敵法、敵方擊中我
344     def hit_tank(self):
345         if self.good:  # 如果是我方炮彈
346             hit_list = pygame.sprite.spritecollide(self, TankMain.enemy_list, True)  # 返回發生碰撞的列表
347             for e in hit_list:
348                 e.live = False
349                 TankMain.enemy_list.remove(e)
350                 self.live = False
351                 explode = Explode(self.screem, e.rect)
352                 TankMain.explode_list.append(explode)
353 
354         else:  # 如果是敵方炮彈
355             pass
356 
357 
358 class Explode(BaseItem):
359     def __init__(self, screem, rect):
360         super().__init__(screem)
361         self.live = True
362         self.screem = screem
363         self.images = [pygame.image.load('image/explode/0.png'), \
364                        pygame.image.load('image/explode/1.png'), \
365                        pygame.image.load('image/explode/2.png'), \
366                        pygame.image.load('image/explode/3.png'), \
367                        pygame.image.load('image/explode/4.png'), \
368                        pygame.image.load('image/explode/5.png'), \
369                        ]
370         self.step = 0
371         self.rect = rect  # 爆炸的位置和發送爆炸前坦克位置一樣,所以傳入坦克位置
372 
373     # 循環調用
374     def display(self):
375         if self.live:
376             if self.step == len(self.images):  # 最后一張爆炸圖片已經顯示
377                 self.live = False
378             else:
379                 self.image = self.images[self.step]
380                 self.screem.blit(self.image, self.rect)
381                 self.step += 1
382 
383         else:
384             pass
385 
386 '''
387 牆:
388     能否被擊毀:
389     能否穿透
390     是否存活
391 草皮:
392     能穿過、不能擊毀、一直存活
393 磚牆:
394     不能闖過、能擊毀、被擊毀則不存活
395 鐵牆:
396     不能穿透、不能擊毀、一直存活
397 '''
398 
399 class SteelsWall(BaseItem):
400     def __init__(self, screem, left, top):
401         super().__init__(screem)
402         self.live = True  # 存活指標
403         self.via = False  # 穿透指標
404         self.quality = True  # 能否被炮彈擊毀,但后來沒用到
405         self.image = pygame.image.load('image/barrier/steels.png')
406         self.rect = self.image.get_rect()
407         self.rect.left = left  # randint(10,500)
408         self.rect.top = top  # randint(10,400)
409     def display(self):
410         if self.live:
411             self.screem.blit(self.image, self.rect)
412         else:
413             pass
414     def hit_tank(self):
415         if TankMain.my_tank and (not self.via) and self.live:
416             hit_list1 = pygame.sprite.collide_circle(self, TankMain.my_tank)
417             if hit_list1:
418                 TankMain.my_tank.stop = True
419                 TankMain.my_tank.stay()  # 我方坦克,調用該函數有點小毛病,穿越?
420             else:
421                 pass
422         if TankMain.enemy_list and (not self.via) and self.live:
423             hit_list2 = pygame.sprite.spritecollide(self, TankMain.enemy_list, False)
424             for e in hit_list2:
425                 e.stop = True
426                 e.stay()  # 略有問題但不明顯
427     def hit_missile(self):
428         missile_list = pygame.sprite.Group()
429         for i in TankMain.enemy_missile_list:
430             missile_list.add(i)
431         for j in (TankMain.my_tank_missile):
432             missile_list.add(j)
433         if missile_list and (not self.via) and self.live:
434             hit_list=pygame.sprite.spritecollide(self,missile_list,False)
435             for missile in hit_list:
436                 missile.stop=True
437                 missile.speed=0
438 
439 class GrassWall(SteelsWall):
440     def __init__(self, screem, left, top):
441         super().__init__(screem, left, top)
442         self.image = pygame.image.load('image/barrier/grasss.png')
443         self.via = True
444 
445 
446 class BlockWall(SteelsWall):
447     def __init__(self, screem, left, top):
448         super().__init__(screem, left, top)
449         self.image = pygame.image.load('image/barrier/walls.png')
450         self.quality = False
451         self.live = True
452         self.via = False
453     def hit_missile(self):
454         missile_group=pygame.sprite.Group()
455         for i in TankMain.enemy_missile_list:
456             missile_group.add(i)
457         for j in TankMain.my_tank_missile:
458             missile_group.add(j)
459         if missile_group:
460             hit_list=pygame.sprite.spritecollide(self,missile_group,False)
461             if hit_list:
462                 self.live=False
463                 for i in hit_list:
464                     i.speed=0
465                     i.stop=True
466                     i.live=False
467             ##提取碼:f9lv 
468 
469 
470 if __name__ == '__main__':
471     game = TankMain()
472     game.startGame()
473     game.stopGame()
474   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM