日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python项目:飞机大战(爆炸效果,血条,音效,buff加成,boss,菜单,完整详细注释的源码)

發(fā)布時間:2023/12/29 python 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python项目:飞机大战(爆炸效果,血条,音效,buff加成,boss,菜单,完整详细注释的源码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一. 總體概覽
    • 基本功能
    • 細節(jié)部分(全部可以自定義)
    • 可增添需求
  • 二,技術框架
    • 核心技術概述
      • 1.游戲的初始化和退出
      • 2 理解游戲中的坐標系
      • 3 創(chuàng)建游戲主窗口
      • 4. 理解 **圖像** 并實現圖像繪制
      • 5. 游戲中的動畫實現原理
        • 游戲循環(huán)的作用
        • 游戲時鐘
      • 6. 在游戲循環(huán)中 監(jiān)聽 事件
        • 事件 `event`
        • 監(jiān)聽
        • 代碼實現
      • 7. 理解 **精靈** 和 **精靈組**
        • 精靈 和 精靈
        • 精靈
        • 精靈組
    • 整體框架
  • 三,實踐中遇到的問題和解決辦法
    • 1.敵機死后,子彈連帶的消失
    • 2.子彈和敵機多次撞擊
    • 3.進行了update卻不顯示
    • 4. 想方設法把一個Sprite或者rect或者image進行清除操作
    • 5. 為什么英雄死掉了,還是會發(fā)生碰撞檢測
    • 6, 如何按鍵不放,移動不止
    • 7,不知道全局變量如何使用
    • 8.明明畫在屏幕上也更新了可就是看不到
  • 三,源代碼
    • 注釋超級詳細
    • 方法比較簡單,很容易看懂
    • 易修改,易擴展,可定制化參數
  • 四, 總結和下載

一. 總體概覽

話不多說,先看效果圖,動作是有聲音的,但是放不出來

看圖片應該大體有個了解,然后我再具體介紹下,游戲有哪些功能和細節(jié)

基本功能

  • 鍵盤方向鍵控制英雄移動
  • 英雄自動發(fā)射子彈
  • 敵軍飛機自動生成,向下運動,發(fā)射不同速度炮彈
  • 自動生成 補給,有子彈buff,炸彈buff,補血buff
    4.1子彈buff最多吃5個,每吃一個子彈數目或者威力提高,吃到第五個召喚"最強形態(tài)"
    4.2炸彈buff可以無限吃,當然出現幾率比較小,吃到的炸彈在屏幕左下角顯示,空格鍵引爆一顆炸彈,毀掉當前所有敵軍飛機,boss損血
    4.3補血buff,一次補滿英雄血條
  • 每種敵軍對應不同分數,英雄擊爆后,屏幕又下角的總分增加相應的分數
  • 子彈擊中和撞擊都會時敵機和英雄損血,且英雄還會debuff,就是buff效果會減弱
  • 當英雄掛掉,游戲結束,屏幕顯示分數,并且可以選擇重來或者結束游戲
  • 細節(jié)部分(全部可以自定義)

  • 英雄吃buff初期子彈威力+1,且子彈排數有序增加,均勻分步
  • 血條低于某個值會變紅,當吃補給增加后又會恢復原色
  • 敵機出現位置隨機,速度隨機,發(fā)射子彈速度隨機,數量排數自定義,低級敵機出場較多,中型后來逐漸增多
  • 英雄,boss有飛行和爆炸動畫,敵機有爆炸動畫
  • 撞擊對不同對象效果不同,英雄撞boss,英雄死boss損血,敵機撞英雄,敵機爆,英雄損血,且損血和被子彈擊中血量不同
  • 背景和bgm循環(huán)移動,營造飛行感覺
  • 每個動作都有專屬音效,如英雄爆,敵機爆,補習,補子彈,補炸彈,扔炸彈,射擊…
  • 三組buff出現頻率不同,且出現時機不同,補血在英雄血條為紅色時優(yōu)先出現
  • boss移動速度慢,慢于最低速度,即1像素每幀,游戲定義為60幀/秒,即速度低于60像素/秒
  • 飛機不能飛出屏幕外面
  • 敵軍死后子彈留著
  • 最強形態(tài)不增加英雄所占面積
  • 爆炸有動畫效果
  • 子彈擊爆敵機后,不繼續(xù)集中殘駭
  • …(細節(jié)部分太多,首先要有個大致的思路,然后在不斷調試中找到最好配置)
  • 可增添需求

    (簡單重復性工作可讓細節(jié)更加到位,代碼看明白后可以自行添加,這是個無底洞,提供個思路)

  • 增加歷史最高分,建立變量每局更新
  • 增加個人中心,記錄分數變化
  • 增加敵機,boss,改變子彈發(fā)射方式
  • 添加更多buff,增添更多特效
  • 增加關卡
  • 讓敵機,buff出現的時機,數量,等級,隨游戲的推進而動態(tài)變化,更加人性化
  • 二,技術框架

    主要就是python類和pygame模塊的運用,有項目文件后直接安裝pygame庫就可以運行了

    核心技術概述

    1.游戲的初始化和退出

    • 要使用 pygame 提供的所有功能之前,需要調用 init 方法
    • 在游戲結束前需要調用一下 quit 方法
    方法說明
    pygame.init()導入并初始化所有 pygame 模塊,使用其他模塊之前,必須先調用 init 方法
    pygame.quit()卸載所有 pygame 模塊,在游戲結束之前調用!
    import pygame

    pygame.init()這個模塊初始化一定不能省略

    游戲代碼…

    pygame.quit()

    2 理解游戲中的坐標系

    • 坐標系

      • 原點左上角 (0, 0)
      • x 軸 水平方向向 ,逐漸增加
      • y 軸 垂直方向向 ,逐漸增加
    • 在游戲中,所有可見的元素 都是以 矩形區(qū)域 來描述位置的

    • 要描述一個矩形區(qū)域有四個要素:(x, y) (width, height)

    • pygame 專門提供了一個類 pygame.Rect 用于描述 矩形區(qū)域

    Rect(x, y, width, height) -> Rect

    3 創(chuàng)建游戲主窗口

    • pygame 專門提供了一個 模塊 pygame.display 用于創(chuàng)建、管理 游戲窗口
    方法說明
    pygame.display.set_mode()初始化游戲顯示窗口
    pygame.display.update()刷新屏幕內容顯示,稍后使用

    set_mode 方法

    set_mode(resolution=(0,0), flags=0, depth=0) -> Surface

    4. 理解 圖像 并實現圖像繪制

    • 在游戲中,能夠看到的 游戲元素 大多都是 圖像
      • 圖像文件 初始是保存在磁盤上的,如果需要使用,第一步 就需要 被加載到內存
    • 要在屏幕上 看到某一個圖像的內容,需要按照三個步驟:
    • 使用 pygame.image.load() 加載圖像的數據
    • 使用 游戲屏幕 對象,調用 blit 方法 將圖像繪制到指定位置
    • 調用 pygame.display.update() 方法更新整個屏幕的顯示
    • 透明圖像
    • png 格式的圖像是支持 透明
    • 在繪制圖像時,透明區(qū)域 不會顯示任何內容
    • 但是如果下方已經有內容,會 透過 透明區(qū)域 顯示出來

    5. 游戲中的動畫實現原理

    • 電影 的原理類似,游戲中的動畫效果,本質上是 快速 的在屏幕上繪制 圖像
      • 電影是將多張 靜止的電影膠片 連續(xù)、快速的播放,產生連貫的視覺效果!
    • 一般在電腦上 每秒繪制 60 次,就能夠達到非常 連續(xù) 高品質 的動畫效果
      • 每次繪制的結果被稱為 幀 Frame

      游戲循環(huán)的開始 就意味著 游戲的正式開始

    游戲循環(huán)的作用

  • 保證游戲 不會直接退出
  • 變化圖像位置 —— 動畫效果
    • 每隔 1 / 60 秒 移動一下所有圖像的位置
    • 調用 pygame.display.update() 更新屏幕顯示
  • 檢測用戶交互 —— 按鍵、鼠標等…
  • 游戲時鐘

    • pygame 專門提供了一個類 pygame.time.Clock 可以非常方便的設置屏幕繪制速度 —— 刷新幀率
    • 要使用 時鐘對象 需要兩步:
      • 1)在 游戲初始化 創(chuàng)建一個 時鐘對象
      • 2)在 游戲循環(huán) 中讓時鐘對象調用 tick(幀率) 方法
    • tick 方法會根據 上次被調用的時間,自動設置 游戲循環(huán) 中的延時

    6. 在游戲循環(huán)中 監(jiān)聽 事件

    事件 event

    • 就是游戲啟動后,用戶針對游戲所做的操作
    • 例如:點擊關閉按鈕點擊鼠標按下鍵盤

    監(jiān)聽

    • 游戲循環(huán) 中,判斷用戶 具體的操作

    只有 捕獲 到用戶具體的操作,才能有針對性的做出響應

    代碼實現

    • pygame 中通過 pygame.event.get() 可以獲得 用戶當前所做動作事件列表
      • 用戶可以同一時間做很多事情
    • 提示:這段代碼非常的固定,幾乎所有的 pygame 游戲都 大同小異
    # 游戲循環(huán) while True:# 設置屏幕刷新幀率clock.tick(60)# 事件監(jiān)聽for event in pygame.event.get():# 判斷用戶是否點擊了關閉按鈕if event.type == pygame.QUIT:print("退出游戲...")pygame.quit()# 直接退出系統(tǒng)exit()

    7. 理解 精靈精靈組

    精靈 和 精靈

    • 為了簡化開發(fā)步驟,pygame 提供了兩個類
      • pygame.sprite.Sprite —— 存儲 圖像數據 image位置 rect對象
      • pygame.sprite.Group

    精靈

    • 在游戲開發(fā)中,通常把 顯示圖像的對象 叫做精靈 Sprite

    • 精靈 需要 有 兩個重要的屬性

      • image 要顯示的圖像
      • rect 圖像要顯示在屏幕的位置
    • 默認的 update() 方法什么事情也沒做

      • 子類可以重寫此方法,在每次刷新屏幕時,更新精靈位置
    • 注意:pygame.sprite.Sprite 并沒有提供 image 和 rect 兩個屬性

      • 需要程序員從 pygame.sprite.Sprite 派生子類
      • 并在 子類初始化方法 中,設置 image 和 rect 屬性

    精靈組

    • 一個 精靈組 可以包含多個 精靈 對象
    • 調用 精靈組 對象的 update() 方法
      • 可以 自動 調用 組內每一個精靈 的 update() 方法
    • 調用 精靈組 對象的 draw(屏幕對象) 方法
      • 可以將 組內每一個精靈 的 image 繪制在 rect 位置

    整體框架


    三,實踐中遇到的問題和解決辦法

    1.敵機死后,子彈連帶的消失

    因為子彈組是敵軍對象的成員,子彈不是
    就是在主函數需要敵軍的子彈再加到一個組,而且所有敵軍的子彈加到一起更更新更加方便,這樣不用擔心敵機毀掉了,他們的子彈對象也訪問不了了.

    2.子彈和敵機多次撞擊

    由于播放爆炸動畫采用的方法是被撞毀時,先不移除精靈組,然后更改該對象圖片,知道圖片輪完了才kill(),這就導致進行下一次循環(huán),對象還沒kill(),kill()了就不能進行輪播.
    思考一:
    撞毀的時候新建循環(huán)把爆炸圖片畫在屏幕上,
    行不通,第循環(huán)一次只能更新一幀圖片,如果你要更新多幀那么其他精靈就會靜止.
    思考二:
    撞毀時候,先移除精靈組,然后用變量儲存,進行最初更新的方法.實驗證明可行.

    3.進行了update卻不顯示

    混淆draw和display.update
    首先一個精靈的update方法讓圖像有改變
    精靈組的draw方法調用screen的blit方法畫到屏幕上
    這時候屏幕畫面殘留在上一幀
    只有display更新了才能看到

    4. 想方設法把一個Sprite或者rect或者image進行清除操作

    其實pygam你們只有貼上去,沒有"撕下來"
    想要看不見他,兩種方法如果是精靈,skill()從所有精靈組里面刪除,如果只是單純的image和rect,直接從他們的list里面remove,這樣就不會被blit,實際上屏幕在更新,如果你想要看到,就要畫在在更新的每一幀上面,之后如果不再用到它,python自己會進行回收.

    同樣的道理,如果希望一個壞人消失,最好的辦法不是你去殺死他,而是從你所在的集體里面孤立排除他,這樣你就再也見不到他了

    5. 為什么英雄死掉了,還是會發(fā)生碰撞檢測

    這是因為,雖然我們把英雄加入英雄隊伍,但是隊伍中英雄很少,為了方便我們碰撞的時候不是從隊伍中取直接就用該英雄對象進行檢測,這時候,英雄skill()了,但是rect并沒有丟失,
    記住skill(),只是把他從需要顯示或者操作群體中把他刪除了,但是這個對象并沒有被立即回收,它的rect還是在,還能用于碰撞檢測

    6, 如何按鍵不放,移動不止

    方向鍵監(jiān)聽有兩種方式
    按一下

    elif event.type ==pygame.KEYDOWN and event.key = = pygame.K_RIGHT:

    按下
    返回所有按鍵的元組,如果某個鍵被按下,對應的值會是1

    keys_pressed = pygame.key.get_pressed() #判斷是否按下了方向鍵if keys_pressed[pygame.K_RIGHT]:

    7,不知道全局變量如何使用

    python里面的全局常量和其他語言一樣是沒有歧義的,但是全局變量就不一樣了,因為python定義變量不用定義類型,只有在賦值的時候才知道,所以在函數里面使用全局變量,無法保證兩個變量是一樣的,所以在函數里面需要用global聲明一下這個變量是我開始設的這個全局變量,不是又重新定義了一個局部變量,

    同樣的道理,全局變量也不能跨模塊調用,即使import了也只能用他的初始值,所以可以建立一個全局變量操作類,用來獲取和修改全局變量.

    8.明明畫在屏幕上也更新了可就是看不到

    注意更新的順序影響圖像的上下層關系

    三,源代碼

    注釋超級詳細

    方法比較簡單,很容易看懂

    易修改,易擴展,可定制化參數

    import random import pygame pygame.init() # ************************************************************** # FileName: plane_sprites.py*************************************** # Author: Junieson ********************************************* # Version: 2019.8.12 ****************************************** # **************************************************************** # 分數 SCORE = 0 # 屏幕大小的常量 SCREEN_RECT = pygame.Rect(0, 0, 480, 700) # color color_blue = (30, 144, 255) color_green = (0, 255, 0) color_red = (255, 0, 0) color_purple = (148, 0, 211) color_gray = (251, 255, 242) # 刷新的幀率 FRAME_PER_SEC = 60 # 刷新率是60hz,即每秒update60次 # 創(chuàng)建敵機的定時器常量,自定義用戶事件,其實就是int數,不同數表示不同事件 CREATE_ENEMY_EVENT = pygame.USEREVENT # 英雄發(fā)射子彈事件 HERO_FIRE_EVENT = pygame.USEREVENT + 1 # buff1 出現的事件 BUFF1_SHOW_UP = pygame.USEREVENT + 2 # buff2 BUFF2_SHOW_UP = pygame.USEREVENT + 3 # 敵軍發(fā)射子彈 ENEMY_FIRE_EVENT = pygame.USEREVENT + 4 # 發(fā)射炸彈 BOMB_THROW = pygame.USEREVENT + 5class GameScore(object):global SCOREdef __init__(self):self.score = 0passdef getvalue(self):self.score = SCOREreturn self.scoreclass GameSprite(pygame.sprite.Sprite):"""飛機大戰(zhàn)游戲精靈"""def __init__(self, image_name, speedy=1, speedx=0):# 調用父類的初始化方法super().__init__()# 定義對象的屬性self.image = pygame.image.load(image_name)self.rect = self.image.get_rect()self.speedy = speedyself.speedx = speedxself.injury = 1self.index = 0 # 記幀數變量self.bar = bloodline(color_blue, self.rect.x, self.rect.y - 10, self.rect.width)def update(self):# 在屏幕的垂直方向上移動self.rect.y += self.speedyself.rect.x += self.speedxself.bar.x = self.rect.xself.bar.y = self.rect.y - 10class Background(GameSprite):"""游戲背景精靈"""def __init__(self, is_alt=False):# 1. 調用父類方法實現精靈的創(chuàng)建(image/rect/speed)super().__init__("./images/background.png")# 2. 判斷是否是交替圖像,如果是,需要設置初始位置if is_alt:self.rect.y = -self.rect.heightdef update(self):# 1. 調用父類的方法實現super().update()# 2. 判斷是否移出屏幕,如果移出屏幕,將圖像設置到屏幕的上方if self.rect.y >= SCREEN_RECT.height:self.rect.y = -self.rect.heightclass Boss(GameSprite):def __init__(self):super().__init__("./images/enemy3_n1.png", 0, 1)self.music_boom = pygame.mixer.Sound("./music/enemy3_down.wav")self.music_fly = pygame.mixer.Sound("./music/enemy3_flying.wav")self.music_fly.play(-1)self.rect.centerx = 240self.y = 200self.isboom = Falseself.number = 3self.index1 = 1 # 控制動畫速度self.index2 = 0self.index3 = 0self.index4 = 0self.injury = 1self.bar = bloodline(color_purple, 0, 0, 480, 8, 200)self.bullets = pygame.sprite.Group()def fire(self):for j in range(2, 7): # 每層5個bullet = Bullet(0, 1)bullet.injury = 1# 2. 設置精靈的位置bullet.rect.centerx = self.rect.centerxbullet.rect.y = self.rect.bottomif j == 2:bullet.speedx = 0else:bullet.speedx = (-1) ** j * ((j - 1) // 2) * 1self.bullets.add(bullet)def update(self):# 左右移global SCOREif self.index4 % 2 == 0: # 降低幀速率,注意這兩個指針不能一樣# 內部為左右移動大概50像素if self.index3 % 50 == 0 and (self.index3 // 50) % 2 == 1:self.speedx = -self.speedxself.rect.x += self.speedxself.index3 += 1self.index4 += 1# 發(fā)電動畫self.image = pygame.image.load("./images/enemy3_n" + str((self.index1 // 6) % 2 + 1) + ".png")self.index1 += 1# 爆炸動畫if self.isboom:self.bar.length -= self.injury * self.bar.weightif self.bar.length <= 0: # 此時滿足爆炸的條件了self.music_fly.stop()if self.index2 == 0:self.music_boom.play()if self.index2 < 29: # 4*7+1self.image = pygame.image.load("./images/enemy3_down" + str(self.index2 // 7) + ".png")# 這個地方之所以要整除4是為了減慢爆炸的速度,如果按照update的頻率60hz就太快了self.index2 += 1else:self.kill()SCORE += self.bar.valueelse:self.isboom = False # 否則還不能死class Enemy(GameSprite):"""敵機精靈"""def __init__(self, num=1):self.number = num# 1. 調用父類方法,創(chuàng)建敵機精靈,同時指定敵機圖片super().__init__("./images/enemy" + str(num) + ".png")# musicif num == 1:self.music_boom = pygame.mixer.Sound("./music/enemy1_down.wav")else:self.music_boom = pygame.mixer.Sound("./music/enemy2_down.wav")# 2. 指定敵機的初始隨機速度 1 ~ 3self.speedy = random.randint(1, 3)# 3. 指定敵機的初始隨機位置self.rect.bottom = 0max_x = SCREEN_RECT.width - self.rect.widthself.rect.x = random.randint(0, max_x)# 4.爆炸效果self.isboom = Falseself.index = 0# 5.血條if self.number == 1:self.bar = bloodline(color_blue, self.rect.x, self.rect.y, self.rect.width)else:self.bar = bloodline(color_blue, self.rect.x, self.rect.y, self.rect.width, 3, 4)# 6,子彈self.bullets = pygame.sprite.Group()def fire(self):for i in range(0, 2):# 1. 創(chuàng)建子彈精靈bullet = Bullet(0, random.randint(self.speedy + 1, self.speedy + 3))# 2. 設置精靈的位置bullet.rect.bottom = self.rect.bottom + i * 20bullet.rect.centerx = self.rect.centerx# 3. 將精靈添加到精靈組self.bullets.add(bullet)def update(self):global SCORE# 1. 調用父類方法,保持垂直方向的飛行super().update()# 2. 判斷是否飛出屏幕,如果是,需要從精靈組刪除敵機if self.rect.y > SCREEN_RECT.height:# print("飛出屏幕,需要從精靈組刪除...")# kill方法可以將精靈從所有精靈組中移出,精靈就會被自動銷毀self.kill()self.bar.length = 0if self.isboom:self.bar.length -= self.bar.weight * self.injuryif self.bar.length <= 0:if self.index == 0: # 保證只響一次self.music_boom.play()if self.index < 17: # 4*4+1self.image = pygame.image.load("./images/enemy" + str(self.number) + "_down" + str(self.index // 4) + ".png")# 這個地方之所以要整除4是為了減慢爆炸的速度,如果按照update的頻率60hz就太快了self.index += 1else:self.kill()SCORE += self.bar.valueelse:self.isboom = Falseclass Hero(GameSprite):"""英雄精靈"""def __init__(self):# 1. 調用父類方法,設置image&speedsuper().__init__("./images/me1.png")self.music_down = pygame.mixer.Sound("./music/me_down.wav")self.music_upgrade = pygame.mixer.Sound("./music/upgrade.wav")self.music_degrade = pygame.mixer.Sound("./music/supply.wav")self.number = 0# 2. 設置英雄的初始位置self.rect.centerx = SCREEN_RECT.centerxself.rect.bottom = SCREEN_RECT.bottom - 120# 3. 創(chuàng)建子彈的精靈組self.bullets = pygame.sprite.Group()# 4.爆炸self.isboom = Falseself.index1 = 1 # 控制動畫速度self.index2 = 0# 5.buff1加成self.buff1_num = 0# 6,英雄血條self.bar = bloodline(color_green, 0, 700, 480, 8, 10)# 7,炸彈數目self.bomb = 0def update(self):# 英雄在水平方向移動和血條不同步,特殊self.rect.y += self.speedyself.rect.x += self.speedx# 控制英雄不能離開屏幕if self.rect.x < 0:self.rect.x = 0elif self.rect.right > SCREEN_RECT.right:self.rect.right = SCREEN_RECT.rightelif self.rect.y < 0:self.rect.y = 0elif self.rect.bottom > SCREEN_RECT.bottom:self.rect.bottom = SCREEN_RECT.bottom# 英雄噴氣動畫self.image = pygame.image.load("./images/me" + str((self.index1 // 6) % 2 + 1) + ".png")self.index1 += 1# 英雄爆炸動畫if self.isboom:self.bar.length -= self.injury * self.bar.weightif self.bar.length <= 0: # 此時滿足爆炸的條件了if self.index2 == 0:self.music_down.play()if self.index2 < 17: # 4*4+1self.image = pygame.image.load("./images/me_destroy_" + str(self.index2 // 4) + ".png")# 這個地方之所以要整除4是為了減慢爆炸的速度,如果按照update的頻率60hz就太快了self.index2 += 1else:self.kill()else:self.isboom = False # 否則還不能死# 發(fā)射子彈def fire(self):if self.buff1_num == 0:for i in range(0, 1):# 1. 創(chuàng)建子彈精靈bullet = Bullet()# 2. 設置精靈的位置bullet.rect.bottom = self.rect.y - i * 20bullet.rect.centerx = self.rect.centerx# 3. 將精靈添加到精靈組self.bullets.add(bullet)elif self.buff1_num <= 3:for i in (0, 1):# 1. 創(chuàng)建子彈精靈for j in range(2, self.buff1_num + 3):bullet = Bullet(2, -3)# 2. 設置精靈的位置bullet.rect.bottom = self.rect.y - i * 20if (self.buff1_num % 2 == 1):bullet.rect.centerx = self.rect.centerx + (-1) ** j * 15 * (j // 2)if (self.buff1_num % 2 == 0):if j == 2:bullet.rect.centerx = self.rect.centerxelse:bullet.rect.centerx = self.rect.centerx + (-1) ** j * 15 * ((j - 1) // 2)# 3. 將精靈添加到精靈組self.bullets.add(bullet)elif self.buff1_num >= 4:for i in range(0, 1):# 1. 表示有幾層for j in range(2, 5): # 每層三個bullet = Bullet(3, -3)bullet.injury = 2# 2. 設置精靈的位置bullet.rect.bottom = self.rect.yif j == 2:bullet.rect.centerx = self.rect.centerxelse:bullet.rect.centerx = self.rect.centerx + (-1) ** j * (30 + 5 * i)bullet.speedx = (-1) ** j * (i + 1)self.bullets.add(bullet)class Heromate(Hero):def __init__(self, num):super().__init__()self.image = pygame.image.load("./images/life.png")self.number = numdef update(self):if self.rect.right > SCREEN_RECT.right:self.rect.right = SCREEN_RECT.rightif self.rect.x < 0:self.rect.x = 0if self.rect.y < 0:self.rect.y = 0elif self.rect.bottom > SCREEN_RECT.bottom:self.rect.bottom = SCREEN_RECT.bottomdef fire(self):for i in range(0, 1, 2):# 1. 創(chuàng)建子彈精靈bullet = Bullet()# 2. 設置精靈的位置bullet.rect.bottom = self.rect.y - i * 20bullet.rect.centerx = self.rect.centerx# 3. 將精靈添加到精靈組self.bullets.add(bullet)class Bullet(GameSprite):"""子彈精靈"""def __init__(self, color=1, speedy=-2, speedx=0):# 調用父類方法,設置子彈圖片,設置初始速度self.hity = color # 子彈傷害值self.music_shoot = pygame.mixer.Sound("./music/bullet.wav")self.music_shoot.set_volume(0.4)if color > 0: # 只讓英雄發(fā)子彈響self.music_shoot.play()super().__init__("./images/bullet" + str(color) + ".png", speedy, speedx)def update(self):# 調用父類方法,讓子彈沿垂直方向飛行super().update()# 判斷子彈是否飛出屏幕if self.rect.bottom < 0 or self.rect.y > 700:self.kill()class Buff1(GameSprite):def __init__(self):super().__init__("./images/bullet_supply.png", 1)self.music_get = pygame.mixer.Sound("./music/get_bullet.wav")self.rect.bottom = 0max_x = SCREEN_RECT.width - self.rect.widthself.rect.x = random.randint(0, max_x)def update(self):super().update()if self.rect.bottom < 0:self.kill()class Buff2(GameSprite):def __init__(self):super().__init__("./images/bomb_supply.png", 2)self.music_get = pygame.mixer.Sound("./music/get_bomb.wav")self.rect.bottom = random.randint(0, 700)max_x = SCREEN_RECT.width - self.rect.widthself.rect.x = random.randint(0, max_x)self.ran = random.randint(60, 180) # 在持續(xù)1~3s后消失def update(self):super().update()if self.rect.bottom < 0 or self.index == self.ran:self.kill()self.index += 1class Buff3(Buff2):def __init__(self):super().__init__()self.image = pygame.image.load("./images/buff3.png")self.speedy=3class bloodline(object):def __init__(self, color, x, y, length, width=2, value=2):self.color = colorself.x = xself.y = yself.length = lengthself.width = width # 線寬self.value = value * 1.0 # 血量用浮點數self.weight = length / value # 每一滴血表示的距離self.color_init = colordef update(self, canvas):if self.length <= self.value * self.weight / 2:self.color = color_redelse:self.color = self.color_initself.bar_rect = pygame.draw.line(canvas, self.color, (self.x, self.y), (self.x + self.length, self.y),self.width)class CanvasOver():def __init__(self, screen):self.img_again = pygame.image.load("./images/again.png")self.img_over = pygame.image.load("./images/gameover.png")self.rect_again = self.img_again.get_rect()self.rect_over = self.img_over.get_rect()self.rect_again.centerx = self.rect_over.centerx = SCREEN_RECT.centerxself.rect_again.bottom = SCREEN_RECT.centeryself.rect_over.y = self.rect_again.bottom + 20self.screen = screendef event_handler(self, event):if event.type == pygame.MOUSEBUTTONDOWN:pos = pygame.mouse.get_pos()if self.rect_again.left < pos[0] < self.rect_again.right and \self.rect_again.top < pos[1] < self.rect_again.bottom:return 1elif self.rect_over.left < pos[0] < self.rect_over.right and \self.rect_over.top < pos[1] < self.rect_over.bottom:return 0def update(self):self.screen.blit(self.img_again, self.rect_again)self.screen.blit(self.img_over, self.rect_over)score_font = pygame.font.Font("./STCAIYUN.ttf", 50)image = score_font.render("SCORE:" + str(int(SCORE)), True, color_gray)rect = image.get_rect()rect.centerx, rect.bottom = SCREEN_RECT.centerx, self.rect_again.top - 20self.screen.blit(image, rect) import sys import pygamepygame.init() from plane_sprites import * # ************************************************************** # FileName: plane_main.py*************************************** # Author: Junieson ********************************************* # Version: 2019.8.12 ****************************************** # **************************************************************** class PlaneGame(object):"""飛機大戰(zhàn)主游戲"""def __init__(self):print("游戲初始化")# 1. 創(chuàng)建游戲的窗口self.screen = pygame.display.set_mode(SCREEN_RECT.size)# 創(chuàng)建結束界面self.canvas_over = CanvasOver(self.screen)# 2. 創(chuàng)建游戲的時鐘self.clock = pygame.time.Clock()# 3. 調用私有方法,精靈和精靈組的創(chuàng)建self.__create_sprites()# 分數對象self.score = GameScore()# 程序控制指針self.index = 0# 音樂bgmself.bg_music = pygame.mixer.Sound("./music/game_music.ogg")self.bg_music.set_volume(0.3)self.bg_music.play(-1)# 游戲結束了嗎self.game_over = False# 4. 設置定時器事件 - 創(chuàng)建敵機 1spygame.time.set_timer(CREATE_ENEMY_EVENT, random.randint(1000, 2000))pygame.time.set_timer(HERO_FIRE_EVENT, 400)pygame.time.set_timer(BUFF1_SHOW_UP, random.randint(10000, 20000))pygame.time.set_timer(BUFF2_SHOW_UP, random.randint(20000, 40000))pygame.time.set_timer(ENEMY_FIRE_EVENT, 2000)def __create_sprites(self):# 創(chuàng)建背景精靈和精靈組bg1 = Background()bg2 = Background(True)self.back_group = pygame.sprite.Group(bg1, bg2)# 創(chuàng)建敵機的精靈組self.enemy_group = pygame.sprite.Group()# 創(chuàng)建英雄的精靈和精靈組self.hero = Hero()self.hero_group = pygame.sprite.Group(self.hero)# 創(chuàng)建敵軍子彈組self.enemy_bullet_group = pygame.sprite.Group()# 血條列表self.bars = []self.bars.append(self.hero.bar)# 創(chuàng)建buff組self.buff1_group = pygame.sprite.Group()# 創(chuàng)建假象boom組self.enemy_boom = pygame.sprite.Group()# bomb列表self.bombs = []def start_game(self):print("游戲開始...")while True:# 1. 設置刷新幀率self.clock.tick(FRAME_PER_SEC)# 2. 事件監(jiān)聽self.__event_handler()# 3. 碰撞檢測self.__check_collide()# 4. 更新/繪制精靈組self.__update_sprites()# 是否要結束游戲if self.game_over:self.canvas_over.update()# 5. 更新顯示pygame.display.update()def __event_handler(self): # 事件檢測if self.score.getvalue() > 200+500*self.index:self.boss = Boss()self.enemy_group.add(self.boss)self.bars.append(self.boss.bar)self.index += 1for event in pygame.event.get():# 判斷是否退出游戲if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == CREATE_ENEMY_EVENT:# 創(chuàng)建敵機精靈將敵機精靈添加到敵機精靈組if self.score.getvalue() < 20:enemy = Enemy()else:if random.randint(0, 100) % 4:enemy = Enemy()else:enemy = Enemy(2)self.enemy_group.add(enemy)self.bars.append(enemy.bar)elif event.type == HERO_FIRE_EVENT:for hero in self.hero_group:hero.fire()elif event.type == BUFF1_SHOW_UP:buff1 = Buff1()self.buff1_group.add(buff1)elif event.type == BUFF2_SHOW_UP:if self.hero.bar.color == color_red:#按需分配buff = Buff3()else:buff= Buff2()self.buff1_group.add(buff)elif event.type == ENEMY_FIRE_EVENT:for enemy in self.enemy_group:if enemy.number >= 2:enemy.fire()for bullet in enemy.bullets:self.enemy_bullet_group.add(bullet)elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:self.bomb_throw()else:if self.game_over == True:flag = self.canvas_over.event_handler(event)if flag == 1:self.__start__()elif flag == 0:pygame.quit()sys.exit()# 使用鍵盤提供的方法獲取鍵盤按鍵 - 按鍵元組keys_pressed = pygame.key.get_pressed()# 判斷元組中對應的按鍵索引值 1if keys_pressed[pygame.K_RIGHT]:self.heros_move(5)elif keys_pressed[pygame.K_LEFT]:self.heros_move(-5)elif keys_pressed[pygame.K_UP]:self.heros_move(0, -5)elif keys_pressed[pygame.K_DOWN]:self.heros_move(0, 5)else:self.heros_move(0, 0)def heros_move(self, x=0, y=0):self.hero.speedx = xself.hero.speedy = ydef bomb_throw(self):music_use_bomb = pygame.mixer.Sound("./music/use_bomb.wav")if self.hero.bomb > 0:music_use_bomb.play()self.hero.bomb -= 1self.bombs.pop()for enemy in self.enemy_group:if enemy.number < 3:enemy.bar.length = 0enemy.isboom = Trueelse:enemy.injury = 20enemy.isboom = Truedef __check_collide(self):# 1. 子彈摧毀敵機for enemy in self.enemy_group:for hero in self.hero_group:for bullet in hero.bullets:if pygame.sprite.collide_mask(bullet, enemy): # 這種碰撞檢測可以精確到像素去掉alpha遮罩的那種哦bullet.kill()enemy.injury = bullet.hityenemy.isboom = Trueif enemy.bar.length <= 0:self.enemy_group.remove(enemy)self.enemy_boom.add(enemy)# 2. 敵機撞毀英雄for enemy in self.enemy_group:if pygame.sprite.collide_mask(self.hero, enemy):if enemy.number < 3:enemy.bar.length = 0 # 敵機直接死self.hero.injury = self.hero.bar.value / 4 # 英雄掉四分之一的血if self.hero.buff1_num > 0:self.hero.buff1_num -= 1self.hero.music_degrade.play()self.enemy_group.remove(enemy)self.enemy_boom.add(enemy)enemy.isboom = Trueelse:self.hero.bar.length = 0self.hero.isboom = True# 子彈摧毀英雄for bullet in self.enemy_bullet_group:if pygame.sprite.collide_mask(self.hero, bullet):bullet.kill()self.hero.injury = 1if self.hero.buff1_num > 0:self.hero.music_degrade.play()if self.hero.buff1_num == 5:self.mate1.kill()self.mate2.kill()self.hero.buff1_num -= 1self.hero.isboom = Trueif not self.hero.alive():self.hero.rect.right = -10 # 把英雄移除屏幕if self.hero.buff1_num == 5:self.mate1.rect.right = -10self.mate2.rect.right = -10self.game_over = True# 3.buff吸收for buff in self.buff1_group:if pygame.sprite.collide_mask(self.hero, buff):buff.music_get.play()if buff.speedy == 1: # 用速度來區(qū)分if self.hero.buff1_num < 6:self.hero.buff1_num += 1self.hero.music_upgrade.play()if self.hero.buff1_num == 5:self.team_show()elif buff.speedy==2:self.hero.bomb += 1image = pygame.image.load("./images/bomb.png")self.bombs.append(image)elif buff.speedy==3:if self.hero.bar.length < self.hero.bar.weight*self.hero.bar.value:self.hero.bar.length += self.hero.bar.weight*self.hero.bar.valuebuff.kill()def team_show(self):self.mate1 = Heromate(-1)self.mate2 = Heromate(1)self.mate1.image = pygame.image.load("./images/life.png")self.mate1.rect = self.mate1.image.get_rect()self.mate2.image = pygame.image.load("./images/life.png")self.mate2.rect = self.mate2.image.get_rect()self.hero_group.add(self.mate1)self.hero_group.add(self.mate2)# 各種更新def __update_sprites(self):self.back_group.update()self.back_group.draw(self.screen)self.enemy_group.update()self.enemy_group.draw(self.screen)self.enemy_boom.update()self.enemy_boom.draw(self.screen)self.heros_update()self.hero_group.draw(self.screen)for hero in self.hero_group:hero.bullets.update()hero.bullets.draw(self.screen)self.buff1_group.update()self.buff1_group.draw(self.screen)self.bars_update()self.bombs_update()self.enemy_bullet_group.update()self.enemy_bullet_group.draw(self.screen)self.score_show()def heros_update(self):for hero in self.hero_group:if hero.number == 1:hero.rect.bottom = self.hero.rect.bottomhero.rect.left = self.hero.rect.rightif hero.number == -1:hero.rect.bottom = self.hero.rect.bottomhero.rect.right = self.hero.rect.lefthero.update()def bars_update(self):for bar in self.bars:if bar.length > 0:bar.update(self.screen)else:self.bars.remove(bar)def bullet_enemy_update(self):for enemy in self.enemy_group:enemy.bullets.update()enemy.bullets.draw(self.screen)def bombs_update(self):i = 1for bomb in self.bombs:self.screen.blit(bomb, (0, 700 - (bomb.get_rect().height) * i))i += 1def score_show(self):score_font = pygame.font.Font("./STCAIYUN.ttf", 33)image = score_font.render("SCORE:" + str(int(self.score.getvalue())), True, color_gray)rect = image.get_rect()rect.bottom, rect.right = 700, 480self.screen.blit(image, rect)@staticmethoddef __start__():# 創(chuàng)建游戲對象game = PlaneGame()# 啟動游戲game.start_game()if __name__ == '__main__':PlaneGame.__start__()

    四, 總結和下載

    這次的項目實踐,讓我對python面相對象程序設計有了更深的體會,也讓我感受到了python語言簡潔優(yōu)雅的美感,如果你覺得還行的話,可以拿去小練一下手,如果有什么問題可以在評論區(qū)留言,我會在第一時間回復,
    敲打不易,順手點個贊吧,
    (づ ̄3 ̄)づ╭?~.鏈接:https://github.com/Junieson/PlaneGame

    總結

    以上是生活随笔為你收集整理的python项目:飞机大战(爆炸效果,血条,音效,buff加成,boss,菜单,完整详细注释的源码)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。