當(dāng)前位置:
首頁(yè) >
python之pygame,详解坦克大战
發(fā)布時(shí)間:2023/12/10
36
豆豆
生活随笔
收集整理的這篇文章主要介紹了
python之pygame,详解坦克大战
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
"""坦克大戰(zhàn)游戲(加深對(duì)面向?qū)ο缶幊痰睦斫?此程序?yàn)樽髡叱鯇W(xué)pygame的練習(xí)作業(yè),請(qǐng)多多指教。)
簡(jiǎn)介:《坦克大戰(zhàn)》是由日本南夢(mèng)宮Namco游戲公司開(kāi)發(fā)的一款平面射擊游戲,于1985年發(fā)售。游戲以坦克戰(zhàn)斗及保衛(wèi)基地為主題,屬于策略型聯(lián)機(jī)類。
同時(shí)也是FC平臺(tái)上少有的內(nèi)建關(guān)卡編輯器的幾個(gè)游戲之一,玩家可自己創(chuàng)建獨(dú)特的關(guān)卡,并通過(guò)獲取一些道具使坦克和基地得到強(qiáng)化。"""
import pygame
import time
from datetime import datetime
from icecream import ic # 使用Python的第三方庫(kù)icecream進(jìn)行打印調(diào)試
import randomdef time_format(): # 定義一個(gè)返回時(shí)間的函數(shù)return f'{datetime.now()}|> 'screen_width = 800 # 定義窗口尺寸、顏色
screen_height = 600
bg_color = pygame.Color(0, 0, 0) # 定義黑色背景
color_red = pygame.Color(255, 0, 0) # 定義紅色,用于左上角的文本框
key_dict = {pygame.K_UP: 'U', pygame.K_DOWN: 'D', pygame.K_LEFT: 'L', pygame.K_RIGHT: 'R'} # 定義pygame的按鍵字典(K_UP:up arrow;K_DOWN:down arrow)
enemy_tank_count = 6 # 定義敵方坦克數(shù)量
enemy_tank_list = [] # 定義列表存儲(chǔ)敵方坦克
my_bullet_list = [] # 定義列表存儲(chǔ)我方坦克子彈
enemy_bullet_list = [] # 定義列表存儲(chǔ)敵方坦克子彈
my_bullet_image = pygame.image.load('坦克大戰(zhàn)素材/my_bullet.png') # 加載我方坦克子彈圖片 pygame.image.load:load new image from a file (or file-like object)
ic.configureOutput(prefix=time_format, includeContext=True) # 先定義函數(shù)time_format,此處才能調(diào)用顯示
# prefix自定義輸出前綴,此處在打印語(yǔ)句中插入代碼執(zhí)行時(shí)間。
# includecontext(顯示文件名、代碼行、函數(shù)信息)值為True,即可輸出代碼執(zhí)行的行和代碼文件
ic(my_bullet_image) # my_bullet_image: <Surface(15x15x32 SW)>,生成一個(gè)surface對(duì)象:寬度x高度x像素位
enemy_bullet_image = pygame.image.load('坦克大戰(zhàn)素材/enemy_bullet.png') # 加載敵方坦克子彈圖片
my_tank_images = {'U': pygame.image.load('坦克大戰(zhàn)素材/wu.gif'),'D': pygame.image.load('坦克大戰(zhàn)素材/wd.gif'),'L': pygame.image.load('坦克大戰(zhàn)素材/wl.gif'),'R': pygame.image.load('坦克大戰(zhàn)素材/wr.gif')} # 用字典(鍵值對(duì))加載我方坦克圖片素材。
enemy_tank_images = {'U': pygame.image.load('坦克大戰(zhàn)素材/eu.gif'),'D': pygame.image.load('坦克大戰(zhàn)素材/ed.gif'),'L': pygame.image.load('坦克大戰(zhàn)素材/el.gif'),'R': pygame.image.load('坦克大戰(zhàn)素材/er.gif')} # 用字典(鍵值對(duì))加載敵方坦克圖片素材
background_image = pygame.image.load('坦克大戰(zhàn)素材/grass.png')
ic(background_image.get_rect()) # 查看圖片尺寸 <rect(0, 0, 800, 600)> 與窗口大小一致
explode_list = [] # 定義列表存儲(chǔ)爆炸效果
wall_list = [] # 定義列表存儲(chǔ)墻壁
wall_image = pygame.image.load('坦克大戰(zhàn)素材/wall.gif') # 加載墻壁圖片
my_tank_bullet_count = 5 # 設(shè)置我方坦克發(fā)射的子彈數(shù)量。限制子彈數(shù)量,節(jié)省內(nèi)存,運(yùn)行流暢。
wall_count = 6 # 定義墻壁的數(shù)量"""主類:開(kāi)始游戲、結(jié)束游戲"""
class MainGame: # 類命名用駝峰原則window = None # 初始化類屬性窗口my_tank = Nonedef __init__(self): # 初始化構(gòu)造函數(shù)pass# 開(kāi)始游戲def start_game(self):pygame.display.init() # 加載主窗口,初始化窗口。初始函數(shù),使用pygame的第一步。返回窗口對(duì)象MainGame.window = pygame.display.set_mode((screen_width, screen_height), 0, 32) # 設(shè)置背景對(duì)話框# 生成主屏幕,調(diào)用類屬性MainGame.window接收# set_mode 函數(shù):會(huì)返回一個(gè) Surface 對(duì)象,代表了在桌面上出現(xiàn)的那個(gè)窗口。# 第1個(gè)參數(shù)為元組,表示屏幕的大小;第2個(gè)標(biāo)志位,如果不用什么特性,就指定 0;第3個(gè)為色深# pygame.display.set_mode:Initialize a window or screen for displaypygame.display.set_caption('Battle City(坦克大戰(zhàn))version1.0') # 設(shè)置當(dāng)前窗口標(biāo)題pygame.display.set_caption:Set the current window caption# 首先生成游戲元素圖片,再進(jìn)入游戲的主循環(huán)self.create_my_tank() # 調(diào)用方法生成我方坦克self.create_enemy_tank() # 調(diào)用方法生成敵方坦克列表self.create_wall() # 調(diào)用方法生成墻壁列表while True: # 游戲循環(huán),意味著游戲的正式開(kāi)始!游戲的主循環(huán)是一個(gè)無(wú)限循環(huán),直到用戶退出。在這個(gè)主循環(huán)里面做的事情就是不停的刷新新畫面MainGame.window.blit(background_image, (0, 0)) # 給窗口設(shè)置背景圖片。必須放在循環(huán)體內(nèi)才能實(shí)現(xiàn)畫面的刷新,達(dá)到動(dòng)畫效果。# MainGame.window.fill(bg_color) # 若不設(shè)置背景圖片,可簡(jiǎn)單的設(shè)置填充色。MainGame.window.blit(self.get_text_surface(f'敵方坦克數(shù)量:{len(enemy_tank_list)}臺(tái)'), (10, 10))# 在主窗口MainGame.window的(10,10)坐標(biāo)處繪制get_text_surface返回的surface對(duì)象,用于顯示文字信息。self.get_event() # 獲取事件(按下方向鍵、關(guān)閉鍵)self.show_enemy_tank() # 調(diào)用顯示敵方坦克,展現(xiàn)敵方坦克的各種操作if MainGame.my_tank and MainGame.my_tank.live: # 判斷我方坦克是否存活。存在且狀態(tài)為活著,則顯示我方坦克,否則不存在即刪除。MainGame.my_tank.display_tank() # 調(diào)用Tank類的display_tank方法進(jìn)行顯示if MainGame.my_tank.switch: # 定義坦克顯示之后的初始狀態(tài)為靜止,若開(kāi)關(guān)為開(kāi),則坦克移動(dòng)。MainGame.my_tank.tank_move() # 根據(jù)按鍵方向控制坦克的移動(dòng)MainGame.my_tank.tank_hit_wall() # 調(diào)用Tank類的tank_hit_wall()方法,判斷我方坦克是否與墻壁碰撞MainGame.my_tank.my_tank_hit_enemy_tank() # 調(diào)用MyTank類的my_tank_hit_enemy_tank()方法,判斷我方坦克與敵方坦克的碰撞else:del MainGame.my_tankMainGame.my_tank = None # 我方坦克消亡后把賦值為空。特殊常量None表示沒(méi)有值,也就是空值。False表示0,也表示空字符串。self.show_wall() # 顯示墻壁self.show_my_bullet() # 調(diào)用方法顯示我方坦克子彈self.show_enemy_bullet() # 調(diào)用方法顯示敵方坦克子彈self.show_explode() # 顯示我方坦克子彈擊中敵方坦克的爆炸效果time.sleep(0.02) # 設(shè)置睡眠時(shí)間,使主程序減速運(yùn)行,以便坦克的行進(jìn)速度適宜pygame.display.update() # 刷新窗口并顯示# 初始化我方坦克def create_my_tank(self): # 初始化我方坦克,傳入坐標(biāo)參數(shù),和速度參數(shù)、坦克圖片參數(shù),調(diào)用類屬性MainGame.my_tank接收MainGame.my_tank = MyTank(screen_width / 2, screen_height / 2, 5, my_tank_images)music = Music('坦克大戰(zhàn)素材/start.wav') # 調(diào)用Music類創(chuàng)建音樂(lè)對(duì)象music.play_music() # 調(diào)用Music類的play_music()方法,播放音樂(lè)# 初始化敵方坦克,并添加到列表中def create_enemy_tank(self):top = 100 # 初始化敵方坦克高度坐標(biāo)enemy_image = pygame.image.load('坦克大戰(zhàn)素材/ed.gif') # 加載敵方坦克圖片enemy_image_width = enemy_image.get_rect().width # 獲取敵方坦克圖片的寬度值ic(enemy_image.get_rect()) # <rect(0, 0, 60, 60)>。pygame.Surface.get_rect():獲取Surface對(duì)象的矩形區(qū)域ic(enemy_image.get_rect().width) # 60ic(list(enemy_image.get_rect())[3]) # 60 ctrl+f可打開(kāi)搜索框ic(enemy_image.get_width()) # 60。pygame.Surface.get_width():獲取Surface對(duì)象的寬度for i in range(enemy_tank_count):left = random.randint(0, screen_width-enemy_image_width) # 隨機(jī)生成敵方坦克的寬度坐標(biāo)值。最大值:屏幕和圖片的寬度差tolerance = random.randint(1, 3) # 隨機(jī)生成敵方坦克的移動(dòng)距離,表現(xiàn)為速度enemy_tank = EnemyTank(left, top, tolerance, enemy_tank_images) # 傳參生成敵方坦克對(duì)象enemy_tank_list.append(enemy_tank) # 將敵方坦克對(duì)象加入敵方坦克列表# 初始化墻壁def create_wall(self):for i in range(wall_count):wall_left = random.randint(0, screen_width - wall_image.get_width()) # 隨機(jī)生成指定寬度范圍內(nèi)墻體的left值wall_top = random.randint(0, screen_height - wall_image.get_height()) # 隨機(jī)生成指定高度范圍內(nèi)墻體的top值wall = Wall(wall_left, wall_top, wall_image) # 生成墻體對(duì)象wall_list.append(wall) # 添加墻體列表的墻體對(duì)象# 繪制左上角文字,用于顯示敵方坦克的實(shí)時(shí)數(shù)量def get_text_surface(self, text): # 定義變量名為textpygame.font.init() # 初始化字體模塊。pygame.font.init:initialize the font module# ic(pygame.font.get_fonts()) # 查看系統(tǒng)所有字體。pygame.font.get_fonts:get all available fontsfont = pygame.font.SysFont('kaiti', 18)# 從系統(tǒng)字體創(chuàng)建字體對(duì)象。pygame.font.SysFont:create a Font object from the system fontstext_surface = font.render(text, True, color_red) # 將需要顯示的文字轉(zhuǎn)換成surface對(duì)象# Pygame.font.Font.render創(chuàng)建一個(gè)新的Surface,并在其上呈現(xiàn)指定的文本。 render(繪制)# 因?yàn)橛螒驘o(wú)法在現(xiàn)有的Surface上直接繪制文本,故需新建一個(gè)Surface對(duì)象。return text_surface# 獲取事件(按下方向鍵、關(guān)閉鍵、坦克重生鍵等)def get_event(self):for event in pygame.event.get(): # 獲取所有事件,返回一個(gè)事件列表并進(jìn)行遍歷列表。# pygame.event.get():get events from the queue將獲取并從隊(duì)列中刪除事件。如果指定一個(gè)或多個(gè) type 參數(shù),那么只獲取并刪除指定類型的事件。if event.type == pygame.QUIT: # 事件類型如果是退出,則結(jié)束游戲。# Event對(duì)象有一個(gè)名為type的成員變量(member variable,也叫作屬性,attributes或properties),它告訴我們對(duì)象表示何種事件。print('welcome back next time!')exit() # 退出窗口。exit()是結(jié)束當(dāng)前程序并且刷新緩沖區(qū)到標(biāo)準(zhǔn)輸出elif event.type == pygame.KEYDOWN: # 判斷事件類型為按下鍵盤if not MainGame.my_tank and event.key == pygame.K_z: # 如果我方坦克不存在,則按下字母鍵z生成我方坦克。self.create_my_tank()if MainGame.my_tank and MainGame.my_tank.live: # 判斷我方坦克是否存活。活著是前提!for pygamekey, direction in key_dict.items(): # 遍歷自定義的pygame的按鍵字典key_dictif event.key == pygamekey: # 判斷按鍵的值ic(event) # eg:<Event(768-KeyDown {'unicode': '', 'key': 1073741906, 'mod': 4096, 'scancode': 82, 'window': None})>ic(event.key) # eg:1073741906MainGame.my_tank.direction = direction # 切換方向MainGame.my_tank.switch = True # 按鍵后,將坦克的開(kāi)關(guān)打開(kāi),使坦克可以移動(dòng)。ic(f'{MainGame.my_tank.direction},move up')if event.key == pygame.K_SPACE: # 定義按下空格鍵為發(fā)射子彈ic('we fire bullets')if len(my_bullet_list) < my_tank_bullet_count: # 若子彈列表的長(zhǎng)度(即子彈數(shù)量)小于限制的子彈數(shù)量,則生成子彈my_bullet = Bullet(MainGame.my_tank, my_bullet_image) # 傳入我方坦克對(duì)象和子彈圖片參數(shù),生成我方坦克的子彈my_bullet_list.append(my_bullet)music = Music('坦克大戰(zhàn)素材/fire.wav') # 生成子彈發(fā)射的音樂(lè)對(duì)象music.play_music() # 播放音樂(lè)else:ic('The bullet is insufficient, no more bullets') # 子彈不足,沒(méi)有更多的子彈了elif event.type == pygame.KEYUP and event.key in key_dict.keys(): # 判斷事件類型為松開(kāi)按鍵(且是方向鍵),坦克停止移動(dòng)if MainGame.my_tank and MainGame.my_tank.live: # 判斷我方坦克是否存活。活著是前提!MainGame.my_tank.switch = False # (over-indented過(guò)度縮進(jìn),檢查縮進(jìn))# 敵方坦克的表現(xiàn)內(nèi)容(在窗口中顯示敵方坦克、敵方坦克的移動(dòng)方法、敵方坦克與墻壁的碰撞處理、敵方坦克與我方坦克的碰撞處理、敵方坦克的消亡)def show_enemy_tank(self): # 需在主循環(huán)中調(diào)用for enemy_tank in enemy_tank_list: # 遍歷敵方坦克列表if enemy_tank.live: # 判斷坦克是否存在enemy_tank.display_tank() # 調(diào)用Tank類的display_tank()方法顯示敵方坦克enemy_tank.rand_move() # 自定義EnemyTank類的坦克移動(dòng)方法rand_move(),隨機(jī)移動(dòng)坦克enemy_tank.tank_hit_wall() # 調(diào)用Tank類的tank_hit_wall()方法,判斷我方坦克是否與墻壁碰撞enemy_tank.enemy_tank_hit_my_tank() # 調(diào)用EnemyTank類的enemy_tank_hit_my_tank()方法,判斷敵方坦克與我方坦克的碰撞num = random.randint(1, 1000) # 設(shè)定敵方坦克發(fā)射子彈的頻率if num <= 20:enemy_bullet = Bullet(enemy_tank, enemy_bullet_image) # 傳入敵方坦克對(duì)象和子彈圖片參數(shù),生成敵方坦克的子彈enemy_bullet_list.append(enemy_bullet)else:enemy_tank_list.remove(enemy_tank) # 敵方坦克不存在時(shí),將從敵方坦克列表中刪除# 我方坦克子彈的表現(xiàn)內(nèi)容(在窗口中顯示我方坦克子彈、子彈的移動(dòng)方法、子彈與敵方坦克的碰撞處理、子彈與墻壁的碰撞處理、子彈的消亡)def show_my_bullet(self): # 需在主循環(huán)中調(diào)用for my_bullet in my_bullet_list:if my_bullet.live: # 若我方子彈狀態(tài)為存在,則顯示并發(fā)射子彈my_bullet.display_bullet() # 調(diào)用子彈類Bullet的子彈顯示方法display_bullet()my_bullet.bullet_move() # 調(diào)用Bullet類的子彈移動(dòng)方法bullet_move()Bullet.my_bullet_hit_enemy_tank(my_bullet) # 檢測(cè)我方子彈是否與敵方坦克發(fā)生碰撞Bullet.bullet_hit_wall(my_bullet) # 檢測(cè)我方子彈是否與墻壁碰撞else:my_bullet_list.remove(my_bullet) # 若我方子彈狀態(tài)為不存在,則調(diào)用列表的remove()方法,將其從子彈列表中刪除。# 敵方坦克子彈的表現(xiàn)內(nèi)容(在窗口中顯示敵方坦克子彈、子彈的移動(dòng)方法、子彈與我方坦克的碰撞處理、子彈與墻壁的碰撞處理、子彈的消亡)def show_enemy_bullet(self): # 需在主循環(huán)中調(diào)用for enemy_bullet in enemy_bullet_list:if enemy_bullet.live: # 若子彈狀態(tài)為存在,則顯示并發(fā)射子彈enemy_bullet.display_bullet() # 調(diào)用子彈類Bullet的子彈顯示方法display_bullet()enemy_bullet.bullet_move() # 調(diào)用Bullet類的子彈移動(dòng)方法bullet_move()Bullet.bullet_hit_wall(enemy_bullet) # 檢測(cè)敵方子彈是否與墻壁碰撞if MainGame.my_tank and MainGame.my_tank.live: # 敵方坦克子彈擊中我方坦克的前提是我方坦克存在Bullet.enemy_bullet_hit_my_tank(enemy_bullet) # 檢測(cè)敵方子彈是否與我方坦克發(fā)生碰撞else:enemy_bullet_list.remove(enemy_bullet) # 若子彈狀態(tài)為不存在,則調(diào)用列表的remove()方法,將其從子彈列表中刪除。# 循環(huán)展示爆炸效果def show_explode(self):for explode in explode_list: # 遍歷爆炸對(duì)象列表if explode.live: # 判斷爆炸是否存在,存在即顯示,否則刪除explode.display_explode() # 調(diào)用Explode類的display_explode()方法,顯示爆炸效果else:explode_list.remove(explode) # 從爆炸列表中刪除爆炸# 顯示墻壁def show_wall(self):for wall in wall_list:if wall.live: # 墻壁存在則展示wall.display_wall()else:wall_list.remove(wall) # 墻壁不存在,則從列表中刪除class BaseItem(pygame.sprite.Sprite): # 定義一個(gè)繼承pygame.sprite.Sprite類的BaseItem類作為中間類,使Tank類和Bullet類共用其屬性。# pygame.sprite.collide_rect:Collision detection between two sprites, using rects。兩個(gè)精靈之間的碰撞檢測(cè),使用rect。# 矩形邊框有交集即碰撞。collide_rect(left, right) -> bool,返回一個(gè)布爾值def __init__(self):pygame.sprite.Sprite.__init__(self)"""坦克類:顯示坦克、移動(dòng)。(坦克射擊的效果由子彈類生成)"""
class Tank(BaseItem): # 定義Tank類繼承BaseItem類,從而也繼承BaseItem類的父類pygame.sprite.Sprite類,即可調(diào)用相應(yīng)的碰撞方法def __init__(self, left, top, tolerance, images): # 定義坐標(biāo)參數(shù):left, top;公差參數(shù):tolerance;圖片參數(shù)imagesself.images = imagesself.direction = random.choice(list(key_dict.values())) # 隨機(jī)初始化坦克方向self.image = self.images[self.direction] # 根據(jù)圖片方向獲取對(duì)應(yīng)的圖片,返回一個(gè)surface對(duì)象ic(self.image.get_rect()) # <rect(0, 0, 60, 60)>self.rect = self.image.get_rect()# pygame.Surface.get_rect:get the rectangular area of the Surface 生成rec對(duì)象# Returns a new rectangle covering the entire surface.# This rectangle will always start at (0, 0) with a width and height the same size as the image.# pygame模塊中rect方法自帶的四個(gè)參數(shù),分別有l(wèi)eft,top,height,width。可列表化list(rect)調(diào)用各個(gè)參數(shù)。self.rect.left = left # 設(shè)置區(qū)域的坐標(biāo)self.rect.top = topself.tolerance = tolerance # 定義按鍵后使rect.left遞增/減的公差,實(shí)現(xiàn)坦克速度的控制。tolerance 寬容,容忍;耐力;公差self.switch = False # 初始定義坦克移動(dòng)狀態(tài)為關(guān)self.live = True # 定義變量live,記錄坦克是否活著,即是否存在self.preleft = self.rect.left # 定義preleft變量,保存當(dāng)前矩形區(qū)域的坐標(biāo)值self.pretop = self.rect.top# 顯示坦克def display_tank(self):self.image = self.images[self.direction] # 獲取展示的對(duì)象MainGame.window.blit(self.image, self.rect) # 將圖片image按照矩形區(qū)域rect的坐標(biāo)顯示在窗口window上。# pygame.Surface.blit:draw one image onto another。將一個(gè)圖像(Surface 對(duì)象)繪制到另一個(gè)圖像上方。# blit:位塊傳送,位塊傳輸,拷貝大量的位 blit surface 塊移圖面# 移動(dòng)坦克def tank_move(self):self.preleft = self.rect.left # 記錄坦克移動(dòng)之前的坐標(biāo)self.pretop = self.rect.topif self.direction == 'L':if self.rect.left > 0:self.rect.left -= self.toleranceelif self.direction == 'R':if self.rect.left+self.rect.height < screen_width:self.rect.left += self.toleranceelif self.direction == 'U':if self.rect.top > 0:self.rect.top -= self.toleranceelif self.direction == 'D':if self.rect.top+self.rect.height < screen_height:self.rect.top += self.tolerance# 坦克還原,使坦克停在原地def restore(self): # 使復(fù)原;使復(fù)位;使復(fù)職;修復(fù);整修self.rect.left = self.preleftself.rect.top = self.pretop# 坦克與墻壁碰撞def tank_hit_wall(self):for wall in wall_list: # 遍歷墻壁列表if pygame.sprite.collide_rect(self, wall): # 若坦克與墻壁碰撞self.restore() # 修復(fù)坦克,還原坐標(biāo)"""敵方坦克類"""
class EnemyTank(Tank): # 繼承Tank類def __init__(self, left, top, tolerance, images): # 定義坐標(biāo)參數(shù):left, top;速度參數(shù):speed;坦克圖片參數(shù):imagessuper(EnemyTank, self).__init__(left, top, tolerance, images) # 子類調(diào)用父類的初始化方法self.step = 60 # 定義步數(shù)變量# 敵方坦克增加一個(gè)變量step步數(shù),因?yàn)橹餮h(huán)while為無(wú)限循環(huán),故可實(shí)現(xiàn)敵方坦克移動(dòng)時(shí)步數(shù)遞減。當(dāng)步數(shù) <= 0,修改敵方坦克的方向,并將步數(shù)復(fù)位。# 敵方坦克隨機(jī)移動(dòng)的方法def rand_move(self):if self.step <= 0: # 當(dāng)步數(shù)<=0時(shí)候修改敵方坦克的方向self.direction = random.choice(list(key_dict.values())) # random.choice(list)從列表中隨機(jī)抽取元素。self.step = 60 # 復(fù)位步數(shù)變量else:self.tank_move()self.step -= 1# 敵方坦克碰撞我方坦克def enemy_tank_hit_my_tank(self):if MainGame.my_tank and MainGame.my_tank.live: # 判斷我方坦克是否存活。活著是前提!if pygame.sprite.collide_rect(self, MainGame.my_tank):self.restore() # 敵方坦克還原"""我方坦克類"""
class MyTank(Tank): # 繼承Tank類def __init__(self, left, top, tolerance, images): # 定義坐標(biāo)參數(shù):left, top;速度參數(shù):speed;坦克圖片參數(shù):imagessuper(MyTank, self).__init__(left, top, tolerance, images) # 子類調(diào)用父類的初始化方法# 我方坦克碰撞敵方坦克def my_tank_hit_enemy_tank(self):for enemy_tank in enemy_tank_list: # 遍歷所有的敵方坦克,判別是否碰撞。if pygame.sprite.collide_rect(self, enemy_tank):self.restore() # 我方坦克位置還原"""子彈類:顯示、移動(dòng)"""
class Bullet(BaseItem): # 定義Bullet類繼承BaseItem類,從而也繼承BaseItem類的父類pygame.sprite.Sprite類,即可調(diào)用相應(yīng)的碰撞方法def __init__(self, tank, image): # 初始化參數(shù)坦克tank(子彈由坦克發(fā)射)self.image = imageself.direction = tank.direction # 子彈方向同坦克方向self.rect = self.image.get_rect() # 獲取子彈圖片的區(qū)域if self.direction == 'U':self.rect.left = tank.rect.left+tank.rect.width/2-self.rect.width/2self.rect.top = tank.rect.top-self.rect.heightif self.direction == 'D':self.rect.left = tank.rect.left+tank.rect.width/2-self.rect.width/2self.rect.top = tank.rect.top+tank.rect.heightif self.direction == 'L':self.rect.left = tank.rect.left-self.rect.widthself.rect.top = tank.rect.top+tank.rect.width/2-self.rect.width/2if self.direction == 'R':self.rect.left = tank.rect.left+tank.rect.heightself.rect.top = tank.rect.top+tank.rect.width/2-self.rect.width/2self.tolerance = 6 # 子彈移動(dòng)的單位距離,控制速度self.live = True # 初始定義存在子彈# 顯示子彈def display_bullet(self):MainGame.window.blit(self.image, self.rect) # 將圖片surface加載到窗口# 移動(dòng)子彈def bullet_move(self):if self.direction == 'U':if self.rect.top > 0:self.rect.top -= self.toleranceelse:self.live = False # 修改子彈狀態(tài)為不存在elif self.direction == 'D':if self.rect.top + self.rect.height < screen_height:self.rect.top += self.toleranceelse:self.live = Falseelif self.direction == 'L':if self.rect.left > 0:self.rect.left -= self.toleranceelse:self.live = Falseelif self.direction == 'R':if self.rect.left + self.rect.width < screen_width:self.rect.left += self.toleranceelse:self.live = False# 我方坦克子彈擊中敵方坦克(即兩者發(fā)生碰撞)def my_bullet_hit_enemy_tank(self):for enemy_tank in enemy_tank_list:if pygame.sprite.collide_rect(enemy_tank, self): # 判斷敵方坦克是否和我方子彈發(fā)射碰撞, 碰撞則產(chǎn)生爆炸效果。music = Music('坦克大戰(zhàn)素材/hit.wav') # 生成碰撞的音樂(lè)對(duì)象(創(chuàng)建爆炸對(duì)象的同時(shí)播放音效)music.play_music() # 播放音樂(lè)enemy_tank.live = False # 修改敵方坦克的狀態(tài)為消亡self.live = False # 修改子彈的狀態(tài)為消亡explode = Explode(enemy_tank) # 生成爆炸對(duì)象explode_list.append(explode) # 爆炸列表中加入爆炸對(duì)象# 敵方坦克子彈擊中我方坦克def enemy_bullet_hit_my_tank(self):if pygame.sprite.collide_rect(MainGame.my_tank, self): # 判斷我方坦克是否和敵方子彈發(fā)射碰撞, 碰撞則產(chǎn)生爆炸效果。explode = Explode(MainGame.my_tank) # 產(chǎn)生爆炸效果music = Music('坦克大戰(zhàn)素材/hit.wav') # 生成碰撞的音樂(lè)對(duì)象(創(chuàng)建爆炸對(duì)象的同時(shí)播放音效)music.play_music() # 播放音樂(lè)explode_list.append(explode) # 爆炸效果添加到爆炸列表中self.live = False # 修改子彈的狀態(tài)為消亡MainGame.my_tank.live = False # 修改我方坦克的狀態(tài)為消亡# 子彈與墻壁碰撞def bullet_hit_wall(self):for wall in wall_list: # 遍歷墻壁列表if pygame.sprite.collide_rect(wall, self): # 若子彈與墻壁碰撞music = Music('坦克大戰(zhàn)素材/hit.wav') # 生成碰撞的音樂(lè)對(duì)象(創(chuàng)建爆炸對(duì)象的同時(shí)播放音效)music.play_music() # 播放音樂(lè)self.live = False # 子彈消亡wall.hp -= 1 # 墻壁的生命值減小if wall.hp < 0: # 當(dāng)墻壁的生命值為負(fù),則墻壁消亡。wall.live = False"""爆炸效果類:展示爆炸"""
class Explode:def __init__(self, tank): # 爆炸的位置由當(dāng)前子彈打中的坦克位置決定, 故將坦克對(duì)象作為參數(shù)傳入。self.rect = tank.rect # 爆炸的位置同坦克的位置self.images = [pygame.image.load('坦克大戰(zhàn)素材/blast0.gif'),pygame.image.load('坦克大戰(zhàn)素材/blast1.gif'),pygame.image.load('坦克大戰(zhàn)素材/blast2.gif'),pygame.image.load('坦克大戰(zhàn)素材/blast3.gif'),pygame.image.load('坦克大戰(zhàn)素材/blast4.gif')] # 用列表加載爆炸效果的圖片集self.step = 0 # 定義參數(shù)step,用于循環(huán)顯示爆炸效果self.image = self.images[self.step] # 讀取爆炸圖片self.live = True # 初始設(shè)定爆炸效果的存在與否# 展示爆炸def display_explode(self):if self.step < len(self.images): # 若step小于圖片列表的長(zhǎng)度則顯示相應(yīng)的爆炸圖片,否則爆炸圖片消亡,從新開(kāi)始self.image = self.images[self.step]MainGame.window.blit(self.image, self.rect) # 將爆炸效果在屏幕上顯示self.step += 1 # 循環(huán)遍歷爆炸效果的圖片,依次進(jìn)行顯示。else:self.live = Falseself.step = 0"""墻壁類:是否通過(guò)墻壁"""
class Wall:def __init__(self, left, top, image):self.image = imageself.rect = self.image.get_rect()self.rect.left = leftself.rect.top = topself.live = Trueself.hp = 3 # 設(shè)置生命值。血量:HP(HealthPoint)。墻壁被子彈擊中四次就消亡。def display_wall(self): # 展示墻壁MainGame.window.blit(self.image, self.rect)"""音效類:播放音樂(lè)"""
class Music:def __init__(self, filename):self.filename = filenamepygame.mixer.init() # 初始化混音器模塊,以進(jìn)行聲音的加載和播放。pygame.mixer.music.load(self.filename) # 加載音樂(lè)文件,并為播放做準(zhǔn)備。# 播放音樂(lè)def play_music(self):pygame.mixer.music.play(loop
[video(video-NsuU6cVA-1612278054153)(type-undefined)(url-undefined)(image-https://img-blog.csdnimg.cn/editor-video.png)(title-undefined)]
s=1) # 啟動(dòng)音樂(lè)流的回放,loops表示重復(fù)播放的次數(shù)。若loops=-1,則表示無(wú)限重復(fù)播放。if __name__ == '__main__':MainGame().start_game()#MainGame().get_text_surface() # 調(diào)用函數(shù)查看字體
總結(jié)
以上是生活随笔為你收集整理的python之pygame,详解坦克大战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux+默认监听+目录,C# 时时监
- 下一篇: python if elif else_