Python快速編程入門(第3版) 課件 第11章 飛機大戰(zhàn)_第1頁
Python快速編程入門(第3版) 課件 第11章 飛機大戰(zhàn)_第2頁
Python快速編程入門(第3版) 課件 第11章 飛機大戰(zhàn)_第3頁
Python快速編程入門(第3版) 課件 第11章 飛機大戰(zhàn)_第4頁
Python快速編程入門(第3版) 課件 第11章 飛機大戰(zhàn)_第5頁
已閱讀5頁,還剩263頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第11章飛機大戰(zhàn)《Python快速編程入門(第3版))》學(xué)習(xí)目標(biāo)/Target010203游戲簡介項目準(zhǔn)備游戲框架搭建04游戲背景和英雄飛機學(xué)習(xí)目標(biāo)/Target050607指示器面板逐幀動畫和飛機類碰撞檢測08音樂和音效章節(jié)概述/Summary飛機大戰(zhàn)是一款由騰訊公司微信團隊推出的內(nèi)置軟件小游戲,擁有簡潔有趣的畫面、易于理解的規(guī)則和簡單易上手的操作,在移動應(yīng)用興起初期曾一度風(fēng)靡。本章將帶領(lǐng)大家使用Pygame庫開發(fā)一個功能較為完整的飛機大戰(zhàn)游戲項目,引導(dǎo)大家在實際開發(fā)中靈活應(yīng)用面向?qū)ο蟮木幊趟枷耄尨蠹以趯W(xué)習(xí)中體驗使用Python語言開發(fā)游戲項目的樂趣。游戲簡介11.1

先定一個小目標(biāo)!了解飛機大戰(zhàn)游戲的規(guī)則,能夠復(fù)述出飛機大戰(zhàn)游戲的規(guī)則11.1游戲簡介飛機大戰(zhàn)游戲主要以太空主題的畫面為游戲背景,由玩家通過鍵盤控制英雄飛機向敵機總部發(fā)動進攻,在進攻的過程中既可以讓英雄飛機發(fā)射子彈或引爆炮彈擊毀敵機以贏取分?jǐn)?shù),也可以拾取道具以增強英雄飛機的戰(zhàn)斗力,一旦被敵機撞毀且生命值為0就結(jié)束游戲。飛機大戰(zhàn)游戲的部分場景如圖所示。11.1游戲簡介飛機大戰(zhàn)游戲中包含眾多游戲元素,例如,大小各異的飛機、連發(fā)的子彈、左上角的游戲分?jǐn)?shù)等。飛機大戰(zhàn)游戲中主要的元素如圖所示。11.1游戲簡介1.背景游戲窗口的整體背景是一張星空圖像,它會以恒定的速度向下緩慢地滾動,讓玩家感覺自己的英雄飛機在向上飛行。2.英雄飛機英雄飛機是由玩家控制的飛機,是飛機大戰(zhàn)游戲的主角,其相關(guān)說明具體如下。(1)英雄飛機在游戲開始時顯示在游戲窗口下方的中央位置。(2)英雄飛機在出場后3秒內(nèi)處于無敵狀態(tài),此時它不會被任何敵機撞毀,也不會撞毀任何敵機。11.1游戲簡介2.英雄飛機(3)玩家可以通過方向鍵↑、↓、←、→控制英雄飛機在游戲窗口范圍內(nèi)向上方、下方、左方和右方移動。(4)英雄飛機出場后每隔0.2秒會自動連續(xù)發(fā)射3顆子彈,即單排子彈。子彈的特征和行為具體介紹如下。特征:子彈的速度為12,殺傷力為1。行為:子彈從英雄飛機的正上方位置發(fā)射,并沿著窗口的垂直方向向上飛行;子彈在被發(fā)射時需要播放發(fā)射子彈的音效;如果子彈在飛行途中擊中敵機,則它會對敵機造成傷害;如果子彈已經(jīng)飛出窗口且在飛行途中未擊中任何敵機,則它會被銷毀。11.1游戲簡介2.英雄飛機(5)英雄飛機出場時默認攜帶3個炸彈,玩家按下“b”鍵可引爆1枚炸彈,此時炸彈數(shù)量減1。炸彈數(shù)量為0時,無法繼續(xù)使用。(6)英雄飛機具有多個動畫和音效。當(dāng)英雄飛機飛行時,顯示飛行動畫;當(dāng)英雄飛機被敵機撞毀時,顯示被撞毀動畫,并播放被撞毀的音效;當(dāng)英雄飛機升級時,播放升級音效。(7)英雄飛機具有多條生命。英雄飛機的初始生命為3;英雄飛機被敵機撞毀時,生命數(shù)量減1;英雄飛機得分每增加10萬,生命數(shù)量加1;英雄飛機的生命數(shù)量歸0時,游戲結(jié)束。游戲窗口的右下方位置會實時顯示英雄飛機的生命數(shù)量。11.1游戲簡介3.敵機敵機的機型有小、中、大三種,各機型均有生命值、速度、分值、圖片和音效等多個特征,且不同類型的敵機所具有的特征也不盡相同,后續(xù)在設(shè)計飛機類時會有詳細說明。飛機大戰(zhàn)游戲中的敵機具有以下行為:(1)敵機出現(xiàn)在游戲窗口頂部的隨機位置。(2)敵機按照各自不同的速度,沿著垂直方向從游戲窗口頂部向下方飛行。(3)若敵機與英雄飛機相撞,則會撞毀英雄飛機。11.1游戲簡介3.敵機(4)若敵機被子彈擊中,則敵機的生命值需要減去子彈的傷害值,此時根據(jù)敵機的生命值可以分如下兩種情況進行處理:如果敵機的生命值大于0,那么將顯示敵機被擊中圖片,讓敵機繼續(xù)向屏幕下方飛行。如果敵機的生命值等于0,那么播放敵機被撞毀動畫與被撞毀音效。在被撞毀動畫播放過程中,該敵機不會在屏幕上移動;在被撞毀動畫播放完成后,該敵機被設(shè)為初始狀態(tài),重新出現(xiàn)在游戲窗口頂部的隨機位置。(5)若敵機飛出了游戲窗口且飛行途中沒有被擊毀,該敵機被設(shè)為初始狀態(tài)。值得一提的是,正在播放被撞毀動畫的敵機屬于已經(jīng)被摧毀的敵機,它既不能被子彈擊中,也不能撞擊英雄飛機。11.1游戲簡介4.道具在游戲過程中,道具每隔30秒會從游戲窗口上方的隨機位置向下飛出,一旦飛出的過程中碰撞到英雄飛機,就會被英雄飛機拾取。飛機大戰(zhàn)游戲總共有兩種道具:炸彈補給和子彈增強,關(guān)于這兩種道具的功能描述如表所示。道具名稱功能描述速度播放音效炸彈補給英雄飛機拾取后,炸彈數(shù)量加15是子彈增強英雄飛機拾取后,發(fā)射的子彈由單排改為雙排,且持續(xù)時長20秒5是11.1游戲簡介5.分?jǐn)?shù)當(dāng)英雄飛機通過子彈或炸彈擊毀敵機時,會獲得與敵機分值相對應(yīng)的分?jǐn)?shù),并將獲得的分?jǐn)?shù)實時地顯示在游戲窗口的左上方位置。同一局游戲的分?jǐn)?shù)會不斷累加,并在下一局開始時自動清零。系統(tǒng)會記錄玩家歷次游戲所得到的最高分,并在游戲暫停和結(jié)束時顯示在游戲窗口上。11.1游戲簡介6.關(guān)卡設(shè)定飛機大戰(zhàn)游戲一共設(shè)立了3個關(guān)卡,依次是關(guān)卡1、關(guān)卡2和關(guān)卡3,其中關(guān)卡1為起始關(guān)卡。在英雄飛機的得分超過當(dāng)前關(guān)卡的預(yù)設(shè)分值之后,游戲會自動進入下一個關(guān)卡。關(guān)卡越高難度越高,敵機數(shù)量和種類越多,速度也更快。3個關(guān)卡的設(shè)定規(guī)則如表所示。關(guān)卡名稱分值范圍小敵機數(shù)量(速度)中敵機數(shù)量(速度)大敵機數(shù)量(速度)關(guān)卡1<1000016(1~3)0(1)0(1)關(guān)卡2<5000024(1~5)2(1)0(1)關(guān)卡3>=5000032(1~7)4(1~3)2(1)11.1游戲簡介

先定一個小目標(biāo)!了解飛機大戰(zhàn)游戲典型場景,能夠復(fù)述出各場景要實現(xiàn)的功能11.2游戲典型場景11.2游戲典型場景飛機大戰(zhàn)游戲的典型事件組成了各個典型場景,除了游戲進行中的場景之外,還包括游戲開始、飛機碰撞、游戲暫停、游戲結(jié)束幾個場景。1.游戲開始游戲開始的場景如圖所示。11.2游戲典型場景在圖中,游戲窗口下方的中心位置顯示了英雄飛機,英雄飛機是游戲的主角,它具備移動自身位置、發(fā)射子彈、引爆炸彈以及拾取道具等功能;游戲窗口右下角顯示了小飛機圖像以及文字“×3”,其中數(shù)字3表示英雄飛機的命數(shù);游戲窗口左下角顯示了炸彈圖像及文字“×3”,其中數(shù)字3表示英雄飛機擁有的炸彈數(shù)量;游戲窗口左上角顯示了游戲狀態(tài)圖像(暫停)和英雄飛機的當(dāng)前得分(0)。需要說明的是,在圖中,除了英雄飛機和背景這兩個元素之外,其他元素的位置都是固定的,但顯示的圖像或者數(shù)字在游戲過程中會發(fā)生改變。2.飛機碰撞英雄飛機與敵機發(fā)生碰撞后被撞毀的某個場景如圖所示。11.2游戲典型場景如果英雄飛機與敵機發(fā)生碰撞,那么它們各自都需要做一些處理,具體如下。(1)英雄飛機發(fā)生碰撞的英雄飛機會被撞毀,并播放被撞毀動畫以及被撞毀音效。被撞毀動畫播放過程中,玩家無法操作英雄飛機;被撞毀動畫播放完成后,英雄飛機的生命數(shù)量減少1。若英雄飛機的生命數(shù)量減少1之后還有剩余命數(shù),則在英雄飛機被撞毀的位置出現(xiàn)一個新的英雄飛機,并由玩家操控新的英雄飛機繼續(xù)戰(zhàn)斗;若英雄飛機沒有剩余命數(shù),則游戲結(jié)束。2.飛機碰撞英雄飛機與敵機發(fā)生碰撞后被撞毀的某個場景如圖所示。11.2游戲典型場景如果英雄飛機與敵機發(fā)生碰撞,那么它們各自都需要做一些處理,具體如下。(2)敵機撞毀英雄飛機的敵機需要播放被撞毀動畫及被撞毀音效。被撞毀動畫播放過程中,敵機顯示在游戲窗口的位置不會移動;被撞毀動畫播放完成后,敵機會被設(shè)置為初始狀態(tài),從屏幕頂部任意位置沿著垂直方向向下飛行。3.游戲暫停玩家按下空格鍵可以暫停游戲,再次按下空格鍵可以恢復(fù)游戲。游戲暫停的某個場景如圖所示。11.2游戲典型場景當(dāng)游戲暫停時,整個游戲畫面靜止,背景音樂停止播放,游戲狀態(tài)圖像會切換為運行圖像,并在窗口中央偏上的位置顯示“GamePaused!”的文字,在“GamePaused!”文字下方顯示最高得分,在最高得分下方顯示“Pressspacebartocontinue.”,提示玩家按下空格鍵可以繼續(xù)游戲。當(dāng)玩家再次按下空格鍵以恢復(fù)游戲時,整個游戲畫面恢復(fù)正常,并繼續(xù)播放背景音樂。游戲狀態(tài)圖像切換回暫停圖像,而窗口中央位置的提示文字全部被隱藏起來。4.游戲結(jié)束英雄飛機被敵機撞毀后若沒有剩余命數(shù)繼續(xù)戰(zhàn)斗,則游戲結(jié)束。在英雄飛機被撞毀的動畫播放完成之后,整個游戲畫面靜止。游戲結(jié)束的某個場景如圖所示。11.2游戲典型場景游戲窗口中央由上至下依次顯示了游戲結(jié)束的提示文字“GameOver!”,最好成績的提示文字“Best:2185000”,以及再來一局的提示文字“Pressspacebartoplayagain.”。玩家按下空格鍵即可重新開始一局游戲。項目準(zhǔn)備11.2

先定一個小目標(biāo)!11.2.1類設(shè)計熟悉項目的準(zhǔn)備工作,能夠獨立設(shè)計游戲的類11.2.1類設(shè)計根據(jù)之前對游戲的介紹,我們可以看到飛機大戰(zhàn)游戲包含許多游戲元素,如英雄飛機、敵機、道具、子彈、游戲狀態(tài)文本、背景音樂和音效等。這些元素都可以通過類進行構(gòu)建,但目前它們分散且缺乏統(tǒng)一的管理。為了方便統(tǒng)一管理這些游戲元素,我們根據(jù)它們的職責(zé)進行了分類。游戲元素的分類及說明如表所示。分類類名說明游戲類Game負責(zé)整個游戲的運行流程指示器面板類HUBPanel負責(zé)統(tǒng)一管理游戲狀態(tài)、游戲分?jǐn)?shù)、炸彈數(shù)量、生命數(shù)量,以及文本提示等與游戲數(shù)據(jù)或狀態(tài)相關(guān)的內(nèi)容音樂播放類MusicPlayer負責(zé)背景音樂和音效的播放游戲背景類Background負責(zé)顯示游戲的背景圖像狀態(tài)按鈕類StatusButton負責(zé)顯示游戲的狀態(tài)按鈕飛機類Plane表示游戲中的飛機,包括英雄飛機和敵機子彈類Bullet表示英雄飛機發(fā)射的子彈道具類Supply負責(zé)管理炸彈補給和子彈增強道具文本標(biāo)簽類Label負責(zé)顯示游戲窗口上的文本11.2.1類設(shè)計游戲元素的分類及說明表中前三個分類負責(zé)管理游戲中獨立的功能,它們可以直接繼承基類object;剩余幾個分類中涉及的游戲元素都是顯示于窗口的圖像,這些元素可以繼承pygame.Sprite類,用于統(tǒng)一組織和管理游戲元素,具體說明如下:(1)游戲背景類、狀態(tài)按鈕類、飛機類、子彈類、道具類負責(zé)顯示的元素都會發(fā)生動態(tài)的變化,它們的共同特征或行為可以抽取成一個游戲元素基類GameSprite,該基類繼承pygame.Sprite類。(2)飛機類表示游戲中的飛機,包括英雄飛機和敵機,這兩種類型的飛機各自具有獨特的特征和行為,因此可以將Plane類派生兩個子類:Hero和Enemy,分別表示游戲中的英雄飛機和敵機。11.2.1類設(shè)計10.2.1模塊的構(gòu)建與使用飛機大戰(zhàn)游戲項目中提煉出的類及類之間的繼承關(guān)系如圖所示。

先定一個小目標(biāo)!11.2.2模塊設(shè)計熟悉項目的準(zhǔn)備工作,能夠獨立設(shè)計游戲的模塊在設(shè)計程序時,我們既要考慮程序的設(shè)計理念和設(shè)計思想,又要考慮程序的結(jié)構(gòu)。結(jié)構(gòu)設(shè)計的原則是代碼模塊化,以便于擴展和維護。為此,我們將飛機大戰(zhàn)游戲項目劃分為四個模塊:game.py、game_items.py、game_hud.py和game_music.py,每個模塊的功能和說明如表所示。11.2.2模塊設(shè)計模塊說明game.py游戲主模塊,封裝Game類并負責(zé)啟動游戲game_items.py游戲元素模塊,封裝英雄飛機、子彈、敵機、道具等游戲元素類,并定義全局變量game_hud.py游戲面板模塊,封裝指示器面板類game_music.py游戲音樂模塊,封裝音樂播放器類

先定一個小目標(biāo)!掌握游戲項目的創(chuàng)建,能夠在PyCharm工具中創(chuàng)建飛機大戰(zhàn)項目11.2.3創(chuàng)建項目打開PyCharm工具,在該工具中新建一個名稱為“飛機大戰(zhàn)”的項目。在飛機大戰(zhàn)項目中依次創(chuàng)建game.py、game_items.py、game_hud.py和game_music.py四個文件,之后將資源文件夾res復(fù)制到飛機大戰(zhàn)項目的目錄下。創(chuàng)建好的項目文件結(jié)構(gòu)如圖所示。11.2.3創(chuàng)建項目res目錄包含3個子目錄:font、images和sound,這3個子目錄分別放置了飛機大戰(zhàn)游戲使用的字體、圖片和聲音素材。游戲框架搭建11.3

先定一個小目標(biāo)!11.3.1游戲類的設(shè)計掌握游戲類的設(shè)計,能夠根據(jù)案例需求設(shè)計游戲類游戲類負責(zé)控制整個游戲的運行流程,它需要包含游戲中的主要元素。Game類的類圖如圖所示。11.3.1游戲類的設(shè)計1.Game類的屬性Game類的屬性可以分為游戲?qū)傩院途`組屬性。精靈表示顯示圖像的對象,游戲窗口中看到的每個單獨圖像或者一行文字都可以看作一個精靈,例如,英雄飛機、一顆子彈、分?jǐn)?shù)標(biāo)簽等。(1)游戲?qū)傩訥ame類中定義的游戲?qū)傩灾饕?個,這些屬性的說明如表所示。11.3.1游戲類的設(shè)計屬性說明main_window游戲主窗口,初始大小為(480,700)is_game_over游戲結(jié)束標(biāo)記,初始值為False,表示游戲未結(jié)束is_pause游戲暫停標(biāo)記,初始值為False,表示游戲未暫停hero英雄精靈,最初顯示在游戲窗口中央靠下位置hud_panel指示器面板,負責(zé)顯示與游戲狀態(tài)以及數(shù)據(jù)相關(guān)的內(nèi)容,包括狀態(tài)圖像、游戲得分、炸彈數(shù)量、英雄飛機的命數(shù),以及游戲暫?;蚪Y(jié)束時顯示在游戲窗口中央位置的提示信息等player音樂播放器,負責(zé)播放背景音樂和游戲音效(2)精靈組屬性精靈組就是保存了多個精靈對象的組,支持將多個精靈對象進行分組,并對組內(nèi)的精靈對象一起進行操作和處理。Pygame的精靈組常用于以下重要的場景。一次性繪制或者更新多個精靈。碰撞檢測。碰撞檢測就是檢測多個精靈之間是否發(fā)生碰撞,例如,子彈是否擊中敵機、敵機是否撞到英雄飛機等。Game類中定義的精靈組屬性總共有3個,這些屬性的說明如表所示。11.3.1游戲類的設(shè)計屬性說明all_group所有精靈組,存放所有要顯示的精靈,用于屏幕繪制和更新位置enemies_group敵機精靈組,存放所有敵機精靈對象,用于檢測子彈擊中敵機以及敵機撞到英雄飛機supplies_group道具精靈組,存放所有道具精靈對象,用于檢測英雄飛機拾取道具2.Game類的方法Game類封裝了多個方法,分別用于創(chuàng)建游戲元素、管理游戲的流程、監(jiān)聽系統(tǒng)事件等。Game類中定義的方法如表所示。11.3.1游戲類的設(shè)計方法說明reset_game()重置游戲。在開啟新一輪游戲前,將游戲?qū)傩曰謴?fù)到初始狀態(tài)create_enemies()創(chuàng)建敵機精靈。在新游戲開始或者關(guān)卡晉級后,根據(jù)當(dāng)前游戲級別創(chuàng)建敵機精靈create_supplies()創(chuàng)建道具。游戲開始后每隔30秒隨機投放炸彈補給或子彈增強道具start()開始游戲。創(chuàng)建時鐘對象并且開啟游戲循環(huán),在游戲循環(huán)中監(jiān)聽事件、更新精靈位置、繪制精靈、更新顯示、設(shè)置刷新幀率event_handler()事件監(jiān)聽。監(jiān)聽并處理每一次游戲循環(huán)執(zhí)行時發(fā)生的事件,避免游戲循環(huán)中的代碼過長check_collide()碰撞檢測。監(jiān)聽并處理每一次游戲循環(huán)執(zhí)行時是否發(fā)生精靈與精靈之間的碰撞,例如,子彈擊中敵機、英雄飛機拾取道具、敵機撞擊英雄飛機等

先定一個小目標(biāo)!11.3.2游戲框架實現(xiàn)掌握游戲框架的搭建方式,能夠獨立搭建游戲的框架1.定義游戲窗口尺寸的全局變量在game_items模塊中,定義一個表示游戲窗口尺寸的全局變量SCREEN_RECT,全局變量的值是使用Rect類創(chuàng)建的矩形對象,矩形對象的寬度和高度分別為480和700像素,具體代碼如下:11.3.2游戲框架實現(xiàn)importpygame#游戲窗口區(qū)域SCREEN_RECT=pygame.Rect(0,0,480,700)2.實現(xiàn)Game類的基礎(chǔ)代碼在game模塊中定義Game類,并實現(xiàn)構(gòu)造方法和重設(shè)游戲方法,具體代碼如下:11.3.2游戲框架實現(xiàn)classGame(object):def__init__(self):#游戲主窗口

self.main_window=pygame.display.set_mode(SCREEN_RECT.size)pygame.display.set_caption("飛機大戰(zhàn)")self.is_game_over=False#游戲結(jié)束標(biāo)記

self.is_pause=False#游戲暫停標(biāo)記

defreset_game(self):"""重設(shè)游戲"""self.is_game_over=False#游戲結(jié)束標(biāo)記

self.is_pause=False#游戲暫停標(biāo)記2.實現(xiàn)Game類的基礎(chǔ)代碼在Game類中定義event_handler()方法,event_handler()方法用于監(jiān)聽游戲循環(huán)中發(fā)生的事件,若監(jiān)聽到退出事件,則返回True,否則返回False,具體代碼如下:11.3.2游戲框架實現(xiàn)defevent_handler(self):foreventinpygame.event.get():ifevent.type==pygame.QUIT:#退出程序

returnTrueelifevent.type==pygame.KEYDOWNand\event.key==pygame.K_ESCAPE:#按下Esc鍵

returnTruereturnFalse2.實現(xiàn)Game類的基礎(chǔ)代碼在Game類中定義start()方法。start()方法用于開始游戲,該方法中首先會創(chuàng)建游戲時鐘,再開啟游戲循環(huán),代碼如下:11.3.2游戲框架實現(xiàn)defstart(self):"""開始游戲"""clock=pygame.time.Clock()#游戲時鐘

whileTrue:ifself.event_handler():#事件監(jiān)聽

returnpygame.display.update()#更新顯示

clock.tick(60)#設(shè)置刷新幀率3.在主模塊中啟動游戲在game模塊的末尾增加以下代碼,創(chuàng)建游戲?qū)ο蟛⑶覇佑螒?,具體代碼如下:11.3.2游戲框架實現(xiàn)if__name__=='__main__':pygame.init()Game().start()pygame.quit()4.使用空格鍵切換游戲狀態(tài)調(diào)整event_handler()方法。在事件監(jiān)聽的循環(huán)體中,增加對空格鍵按鍵事件的監(jiān)聽,并在監(jiān)聽到空格鍵按下的事件時切換游戲狀態(tài),具體代碼如下:11.3.2游戲框架實現(xiàn)elifevent.type==pygame.KEYDOWNandevent.key==pygame.K_SPACE:ifself.is_game_over:#游戲已經(jīng)結(jié)束

self.reset_game()else:#切換暫停狀態(tài)

self.is_pause=notself.is_pause4.使用空格鍵切換游戲狀態(tài)在游戲循環(huán)語句中增加判斷游戲狀態(tài)的邏輯代碼:若游戲已經(jīng)結(jié)束,則輸出游戲結(jié)束狀態(tài)的提示文字;若游戲暫停,則輸出游戲暫停狀態(tài)的提示文字;若游戲正在進行中,則輸出游戲狀態(tài)的提示文字。11.3.2游戲框架實現(xiàn)defstart(self):clock=pygame.time.Clock()#游戲時鐘

whileTrue:ifself.event_handler():#事件監(jiān)聽

Returnifself.is_game_over:#判斷游戲狀態(tài)print("游戲已經(jīng)結(jié)束,按空格鍵重新開始...")elifself.is_pause:print("游戲已經(jīng)暫停,按空格鍵繼續(xù)...")else:print("游戲進行中...")pygame.display.update()#更新顯示

clock.tick(60)#設(shè)置刷新幀率如果想要測試游戲結(jié)束后使用空格鍵重新開始游戲的功能,可以通過將構(gòu)造方法中is_game_over屬性的值暫時設(shè)置為True,再進行測試。注意,測試結(jié)束后應(yīng)將is_game_over屬性的值設(shè)置為False。11.3.2游戲框架實現(xiàn)游戲背景和英雄飛機11.4

先定一個小目標(biāo)!11.4.1介紹精靈和精靈組熟悉精靈和精靈組,能夠歸納精靈和精靈組的作用飛機大戰(zhàn)項目中需要管理多種游戲?qū)ο?,如敵機、英雄飛機和子彈。此外,還需要實現(xiàn)許多動畫效果,如英雄飛機的飛行動畫和飛機的碰撞動畫等等。為了保證游戲?qū)ο蟮娘@示和動畫效果,我們可以使用精靈和精靈組管理它們。11.4.1介紹精靈和精靈組Pygame專門提供了兩個類:Sprite和Group,分別表示精靈和精靈組,其中精靈是指游戲中顯示圖像的對象,比如英雄飛機、敵機、子彈等;精靈組是保存和管理一組精靈對象的容器。通過添加精靈對象到組中,可以實現(xiàn)一次性對組中所有精靈對象進行操作,例如更新、繪制、碰撞檢測等。11.4.1介紹精靈和精靈組1.Sprite類Sprite用于創(chuàng)建游戲中精靈對象的基類,該類提供了一些屬性和方法操作或管理精靈對象。常用屬性和方法如表所示。11.4.1介紹精靈和精靈組類型名稱說明屬性imageimage屬性用于存儲精靈對象的圖像內(nèi)容。這個圖像可以是從磁盤上加載的圖片,也可以是通過字體渲染出的文本內(nèi)容。注意,Sprite的子類中必須手動設(shè)置image屬性rect表示精靈對象在游戲窗口的矩形區(qū)域。注意,Sprite的子類中必須手動設(shè)置rect屬性方法update(*args,**kwargs)用于更新精靈對象的狀態(tài)和屬性。默認情況下,此方法不執(zhí)行任何操作。子類可以重寫update()方法實現(xiàn)自定義的更新邏輯,例如改變精靈的位置或顯示內(nèi)容add(*groups)將精靈添加到指定的精靈組中remove(*groups)將精靈從指定的精靈組中移除kill()將精靈從所有精靈組中移除并銷毀2.Group類Group是一個包含多個精靈的容器類,該類中提供了一些管理精靈的常用方法,關(guān)于這些常用方法的說明如表所示。游戲中精靈對象的基類,該類提供了一些屬性和方法操作或管理精靈對象。常用屬性和方法如表所示。11.4.1介紹精靈和精靈組名稱說明update(*args,**kwargs)更新組內(nèi)所有精靈的狀態(tài),如位置或顯示內(nèi)容等draw(surface)在指定表面上一次繪制組內(nèi)的所有精靈對象sprites()返回精靈組中所有精靈的列表add(*sprites)向精靈組中添加一個或多個精靈remove(*sprites)從精靈組中移除一個或多個精靈empty()清空精靈組中所有的精靈

先定一個小目標(biāo)!11.4.2派生游戲精靈子類熟悉派生游戲精靈子類,能夠歸納派生游戲精靈子類的使用根據(jù)Pygame官方文檔的建議,我們應(yīng)該在實際開發(fā)中使用派生自Sprite類的子類,而不是直接使用Sprite類。以下是關(guān)于派生自Sprite類的子類的注意事項,具體內(nèi)容如下:子類可以重寫update()方法。子類必須為image和rect屬性賦值。子類的構(gòu)造方法可以接收任意數(shù)量的精靈組對象,以將創(chuàng)建完成的精靈對象添加到指定的精靈組中。子類的構(gòu)造方法中必須調(diào)用父類的構(gòu)造方法,這樣才能向精靈組中添加精靈。11.4.2派生游戲精靈子類在game_items模塊中定義派生自Sprite的子類GameSprite,GameSprite類的類圖如圖所示。11.4.2派生游戲精靈子類定義GameSprite類,具體代碼如下:11.4.2派生游戲精靈子類classGameSprite(pygame.sprite.Sprite):"""游戲精靈類"""res_path="./res/images/"#圖片資源路徑

def__init__(self,image_name,speed,*groups):super().__init__(*groups)#圖像

self.image=pygame.image.load(self.res_path+image_name)self.rect=self.image.get_rect()#矩形區(qū)域,默認在左上角

self.speed=speed#移動速度

defupdate(self,*args):self.rect.y+=self.speed

先定一個小目標(biāo)!11.4.3繪制游戲背景和英雄飛機掌握繪制游戲背景和英雄飛機,能夠?qū)崿F(xiàn)繪制飛機大戰(zhàn)的游戲背景和英雄飛機按照Game類的類圖,在Game類的構(gòu)造方法中創(chuàng)建3個精靈組,并且創(chuàng)建背景精靈和英雄精靈,代碼如下。#精靈組屬性self.all_group=pygame.sprite.Group()#所有精靈組self.enemies_group=pygame.sprite.Group()#敵機精靈組self.supplies_group=pygame.sprite.Group()#道具精靈組#創(chuàng)建精靈#背景精靈,向下方移動GameSprite("background.png",1,self.all_group)#英雄精靈,靜止不動hero=GameSprite("me1.png",0,self.all_group)hero.rect.center=SCREEN_RECT.center#顯示在屏幕中央11.4.3繪制游戲背景和英雄飛機在判斷游戲狀態(tài)之后、更新顯示之前增加負責(zé)繪制和更新所有精靈的代碼,修改后的代碼如下:defstart(self):……#判斷游戲狀態(tài)

ifself.is_game_over:print("游戲已經(jīng)結(jié)束,按空格鍵重新開始...")elifself.is_pause:print("游戲已經(jīng)暫停,按空格鍵繼續(xù)...")else:self.all_group.update()#更新all_group中所有精靈內(nèi)容self.all_group.draw(self.main_window)#繪制all_group中的所有精靈pygame.display.update()#更新顯示

clock.tick(60)#設(shè)置刷新幀率11.4.3繪制游戲背景和英雄飛機運行游戲,可以在游戲窗口中看到緩緩向下移動的星空背景和英雄飛機,如圖所示。11.4.3繪制游戲背景和英雄飛機

先定一個小目標(biāo)!11.4.4實現(xiàn)游戲背景連續(xù)滾動掌握游戲背景連續(xù)滾動,能夠?qū)崿F(xiàn)在飛機大戰(zhàn)中實現(xiàn)游戲背景連續(xù)滾動11.4.4實現(xiàn)游戲背景連續(xù)滾動當(dāng)我們運行上個小節(jié)實現(xiàn)的程序時,注意到游戲剛啟動時,背景圖像填滿了整個游戲窗口。但是隨著背景圖像緩慢向下移動,游戲窗口上方會逐漸出現(xiàn)一個越來越大的灰色無圖區(qū)域。那么,如何實現(xiàn)背景圖像的連續(xù)滾動效果呢?解決方法是使用兩個背景精靈:背景精靈1和背景精靈2。使用這兩個背景精靈實現(xiàn)背景圖像連續(xù)滾動的原理圖,具體如圖所示。11.4.4實現(xiàn)游戲背景連續(xù)滾動11.4.4實現(xiàn)游戲背景連續(xù)滾動使用兩個背景精靈實現(xiàn)背景圖像連續(xù)滾動的原理,連續(xù)滾動的完整過程可以拆分成以下步驟:(1)背景精靈1與窗口重合;背景精靈2放在窗口的正上方,與背景精靈1連接。(2)兩個背景精靈同時向下移動。(3)當(dāng)背景精靈1移出窗口底部時,背景精靈2正好完全顯示在窗口上。(4)背景精靈1立即移動到窗口的上方,與背景精靈2連接。(5)兩個背景精靈繼續(xù)同時向下移動,回到步驟(2)。11.4.4實現(xiàn)游戲背景連續(xù)滾動在代碼實現(xiàn)時,可以通過檢查背景精靈的y值是否大于等于窗口的h值來判斷背景精靈是否移出窗口的底部。如果背景精靈已經(jīng)移出窗口,則可以將背景精靈的y值設(shè)置為其高度的負值,將其從窗口下方移動到窗口的上方。理解了背景圖像連續(xù)滾動的實現(xiàn)原理之后,根據(jù)背景圖像的特征和行為設(shè)計背景精靈類Background。Background類的類圖如圖所示。11.4.4實現(xiàn)游戲背景連續(xù)滾動11.4.4實現(xiàn)游戲背景連續(xù)滾動由Background類的類圖可知,背景精靈類繼承自GameSprite,并且包含重寫的構(gòu)造方法__init__()和update()方法。__init__()方法中有一個參數(shù)is_alt,用于區(qū)別兩個背景精靈:若is_alt的值為False,表示第一個背景精靈的初始矩形區(qū)域應(yīng)該與游戲窗口重疊;若is_alt的值為True,表示另一個背景精靈的初始矩形區(qū)域應(yīng)該在游戲窗口的正上方。11.4.4實現(xiàn)游戲背景連續(xù)滾動Background類中之所以要重寫update()方法,是因為需要判斷圖像是否已經(jīng)移出游戲窗口。一旦檢測到圖像已經(jīng)移出游戲窗口,就需要將背景精靈重新定位到游戲窗口正上方,以實現(xiàn)連續(xù)滾動的效果。在game_items文件中,添加BackGround類的定義,具體代碼如下:classBackground(GameSprite):"""背景精靈類"""def__init__(self,is_alt,*groups):#調(diào)用父類方法實現(xiàn)精靈的創(chuàng)建

super().__init__("background.png",1,*groups)ifis_alt:#判斷是否是另一個精靈,如果是則需要設(shè)置初始位置

self.rect.y=-self.rect.h#將圖像設(shè)置到窗口上方

defupdate(self,*args):#調(diào)用父類的方法實現(xiàn)向下移動的效果

super().update(*args)#向下移動

#判斷是否移出窗口,如果移出窗口,將圖像設(shè)置到窗口上方

ifself.rect.y>=self.rect.h:self.rect.y=-self.rect.h11.4.4實現(xiàn)游戲背景連續(xù)滾動修改Game類中創(chuàng)建背景精靈的代碼,創(chuàng)建兩個背景精靈并將它們?nèi)刻砑拥骄`組中,具體代碼如下:def__init__(self):#游戲主窗口

self.main_window=pygame.display.set_mode(SCREEN_RECT.size)pygame.display.set_caption("飛機大戰(zhàn)")……#背景精靈,交替位置實現(xiàn)連續(xù)滾動

self.all_group.add(Background(False),Background(True))11.4.4實現(xiàn)游戲背景連續(xù)滾動運行游戲,可以看到背景圖像持續(xù)向窗口下方移動,沒有出現(xiàn)無背景圖像的情況,如圖所示。11.4.4實現(xiàn)游戲背景連續(xù)滾動指示器面板11.5

先定一個小目標(biāo)!11.5.1指示器面板類的設(shè)計熟悉精靈和精靈組,能夠歸納精靈和精靈組的作用11.5.1指示器面板類的設(shè)計指示器面板又稱HUD(平視顯示器,全稱為HeadUpDisplay),是航空器上的飛行輔助儀器。在游戲開發(fā)中,我們借鑒了指示器面板概念,以類似的方式將游戲相關(guān)信息顯示在游戲畫面上,使玩家能夠隨時了解最重要、最直接的游戲信息。在飛機大戰(zhàn)游戲中,指示器面板負責(zé)顯示與游戲狀態(tài)和數(shù)據(jù)相關(guān)的內(nèi)容,包括狀態(tài)圖像、游戲得分、炸彈圖像、炸彈數(shù)量、英雄命數(shù)等,同時還會在游戲暫?;蚪Y(jié)束時在游戲窗口中央顯示相應(yīng)的提示信息。指示器面板類HudPanel的類圖如圖所示。11.5.1指示器面板類的設(shè)計1.HudPanel的屬性HudPanel類的屬性可以分為游戲數(shù)據(jù)屬性和精靈屬性,其中游戲數(shù)據(jù)屬性是一些指示器面板中變化的數(shù)據(jù);精靈屬性是一些指示器面板中顯示圖像的精靈,關(guān)于它們的介紹如下。(1)游戲數(shù)據(jù)屬性HudPanel類中封裝了4個與游戲數(shù)據(jù)相關(guān)的屬性,關(guān)于這些屬性的說明如表所示。11.5.1指示器面板類的設(shè)計屬性說明score游戲得分,初始值為0lives_count生命計數(shù),即英雄飛機的命數(shù),初始值為3level游戲級別,初始值為1best_score最好成績,保存在record.txt文件中HudPanel類中封裝了3個圖像精靈和6個標(biāo)簽精靈屬性,關(guān)于這些精靈屬性的說明如表所示。11.5.1指示器面板類的設(shè)計屬性說明status_sprite狀態(tài)精靈,顯示在游戲窗口左上角bomb_sprite炸彈精靈,顯示在游戲窗口左下角lives_sprite生命計數(shù)精靈,顯示在游戲窗口右下角score_label得分標(biāo)簽,顯示在狀態(tài)精靈的右側(cè)bomb_label炸彈計數(shù)標(biāo)簽,顯示在炸彈精靈的右側(cè)lives_label生命計數(shù)標(biāo)簽,顯示在生命計數(shù)精靈的右側(cè)best_label最好成績標(biāo)簽,顯示在游戲窗口中央status_label狀態(tài)標(biāo)簽,顯示在最好成績標(biāo)簽上方,標(biāo)簽的文字內(nèi)容為GameOver!或者GamePaused!tip_label提示標(biāo)簽,顯示在最好成績標(biāo)簽下方,游戲暫?;蛘呓Y(jié)束時的文字內(nèi)容分別為“Pressspacebartocontinue.”或“Pressspacebartoplayagain.”需要注意的是,HudPanel類的職責(zé)僅限于游戲數(shù)據(jù)的維護和指示器面板相關(guān)精靈的創(chuàng)建,而精靈的繪制和更新操作則主要在游戲循環(huán)中進行。為此,可以考慮在HudPanel類的構(gòu)造方法中添加一個display_group參數(shù),通過該參數(shù)傳遞負責(zé)更新和繪制的精靈組對象。這樣,在創(chuàng)建HudPanel類的對象時,可以將創(chuàng)建好的精靈添加到精靈組中,并在游戲循環(huán)中進行統(tǒng)一的繪制和更新操作。11.5.1指示器面板類的設(shè)計2.HudPanel類的方法HudPanel類中封裝了眾多負責(zé)顯示和更新數(shù)據(jù)、游戲狀態(tài)的方法,關(guān)于這些方法的說明如表所示。11.5.1指示器面板類的設(shè)計方法說明reset_panel()重置面板數(shù)據(jù)。開啟新一輪游戲之前,將游戲數(shù)據(jù)屬性恢復(fù)為初始值show_bomb()顯示炸彈數(shù)量。根據(jù)傳入的炸彈數(shù)量,更改炸彈計數(shù)標(biāo)簽顯示show_lives()顯示生命計數(shù)。使用英雄命數(shù)更新生命計數(shù)標(biāo)簽顯示increase_score()增加分?jǐn)?shù)。根據(jù)消滅的敵機分值增加游戲得分、計算是否獎勵生命、調(diào)整最好成績以及計算游戲級別,并且更改分?jǐn)?shù)標(biāo)簽顯示load_best_score()加載最好成績。從record.txt文件中加載最好成績save_best_socre()保存最好成績。將最好成績保存到record.txt文件中panel_paused()面板暫停。當(dāng)游戲暫?;蚪Y(jié)束時,在游戲窗口中央位置顯示游戲暫?;蚪Y(jié)束的提示信息panel_resume()面板恢復(fù)。當(dāng)游戲運行時,隱藏游戲窗口中央位置的提示信息

先定一個小目標(biāo)!11.5.2指示器面板類的準(zhǔn)備掌握指示器面板類的準(zhǔn)備,能夠定義指示器面板類、設(shè)計狀態(tài)按鈕類以及創(chuàng)建圖像精靈11.5.2指示器面板類的準(zhǔn)備指示器面板類的準(zhǔn)備工作,包括定義指示器面板類、設(shè)計狀態(tài)按鈕類以及創(chuàng)建圖像精靈,具體內(nèi)容如下。1.定義指示器面板類在game_hud模塊中定義HudPanel類,并在該類的構(gòu)造方法中添加游戲?qū)傩?,具體代碼如下:importpygamefromgame_itemsimport*classHUDPanel:"""指示器面板類"""def__init__(self,display_group):#游戲?qū)傩?/p>

self.score=0游戲得分

self.lives_count=3#生命計數(shù)

self.level=1#游戲級別

self.best_score=0#最好成績HUDPanel類本身并不是一個精靈,它只是一個負責(zé)管理游戲數(shù)據(jù)以及多個精靈的面板。11.5.2指示器面板類的準(zhǔn)備2.設(shè)計狀態(tài)按鈕類根據(jù)游戲介紹,當(dāng)玩家按下空格鍵暫?;蚶^續(xù)游戲時,游戲窗口左上角的狀態(tài)精靈會根據(jù)操作發(fā)生相應(yīng)的變化。為了方便后續(xù)的代碼編寫,可以從GameSprite類派生一個子類StatusButton類,通過StatusButton類來處理狀態(tài)圖像的切換操作。StatusButton類的類圖如圖所示。11.5.2指示器面板類的準(zhǔn)備在game_items模塊中定義一個繼承GameSprite類的子類StatusButton類,具體代碼如下:classStatusButton(GameSprite):"""狀態(tài)按鈕類"""def__init__(self,image_names,*groups):super().__init__(image_names[0],0,*groups)#加載圖像

self.images=[pygame.image.load(self.res_path+name)fornameinimage_names]defswitch_status(self,is_pause):self.image=self.images[1ifis_pauseelse0]11.5.2指示器面板類的準(zhǔn)備3.創(chuàng)建圖像精靈在HUDPanel類的構(gòu)造方法中創(chuàng)建指示器面板中的圖像精靈,包括左上角的狀態(tài)精靈(暫停或繼續(xù)圖像)、左下角的炸彈精靈(炸彈圖像),以及右下角的生命計數(shù)精靈(小飛機圖像),具體步驟如下。首先,在HUDPanel類中構(gòu)造方法上方定義一些類屬性,方便后續(xù)可以設(shè)置精靈的矩形區(qū)域和標(biāo)簽精靈的字體顏色,具體代碼如下:classHUDPanel(object):"""指示器面板類"""margin=10#精靈之間的間距

white=(255,255,255) #白色

gray=(64,64,64) #灰色

def__init__(self,display_group):……11.5.2指示器面板類的準(zhǔn)備3.創(chuàng)建圖像精靈然后,在構(gòu)造方法的末尾創(chuàng)建精靈并設(shè)置精靈的顯示位置,具體代碼如下:#創(chuàng)建圖像精靈#狀態(tài)精靈self.status_sprite=StatusButton(("pause.png","resume.png"),display_group)self.status_sprite.rect.topleft=(self.margin,self.margin)self.bomb_sprite=GameSprite("bomb.png",0,display_group)#炸彈精靈self.bomb_sprite.rect.x=self.marginself.bomb_sprite.rect.bottom=SCREEN_RECT.bottom-self.margin#生命計數(shù)精靈self.lives_sprite=GameSprite("life.png",0,display_group)self.lives_sprite.rect.right=SCREEN_RECT.right-self.marginself.lives_sprite.rect.bottom=SCREEN_RECT.bottom-self.margin11.5.2指示器面板類的準(zhǔn)備3.創(chuàng)建圖像精靈最后,在Game類的構(gòu)造方法末尾創(chuàng)建指示器面板對象,具體代碼如下:#指示器面板self.hud_panel=HUDPanel(self.all_group)

先定一個小目標(biāo)!11.5.3使用精靈實現(xiàn)文本標(biāo)簽掌握文本標(biāo)簽的使用,能夠使用精靈實現(xiàn)文本標(biāo)簽由于系統(tǒng)字體不太符合游戲的視覺風(fēng)格,所以需要使用自定義字體定義文本標(biāo)簽精靈,之后再創(chuàng)建指示器面板的文本標(biāo)簽精靈,具體內(nèi)容如下。1.使用自定義字體定義文本標(biāo)簽精靈Pygame的font模塊提供了SysFont類,使用SysFont類可以創(chuàng)建系統(tǒng)字體對象,實現(xiàn)在游戲窗口中繪制文字內(nèi)容。但系統(tǒng)字體存在以下幾點限制:不夠美觀。一般操作系統(tǒng)默認提供的字體大多比較規(guī)整,直接應(yīng)用到游戲中,呈現(xiàn)的效果比較呆板。不支持跨平臺。不同操作系統(tǒng)使用的系統(tǒng)字體的名稱不同,當(dāng)一個程序被移植到其他類型的操作系統(tǒng)運行時,可能會導(dǎo)致文字內(nèi)容無法被正確顯示。11.5.3使用精靈實現(xiàn)文本標(biāo)簽1.使用自定義字體定義文本標(biāo)簽精靈在游戲開發(fā)中,若希望擁有美觀的字體,又需要確保游戲能夠跨平臺運行。為了實現(xiàn)這一目標(biāo),使用自定義字體將是一個不錯的選擇。使用自定義字體的方法是將字體文件與程序文件保存在同一個目錄下。在程序執(zhí)行時,可以直接加載并使用該目錄下的字體文件;而在程序移植時,只需將字體文件復(fù)制到相應(yīng)的目錄即可。pygame的font模塊還提供了另外一個Font類,使用Font類可以創(chuàng)建自定義字體對象。在game_items模塊中派生一個pygame.sprite.Sprite類的子類Label。Label類的類圖如圖所示。11.5.3使用精靈實現(xiàn)文本標(biāo)簽11.5.3使用精靈實現(xiàn)文本標(biāo)簽因為文本標(biāo)簽的內(nèi)容并不需要在每一次游戲循環(huán)執(zhí)行時發(fā)生變化,所以Label類無須重寫update()方法。在游戲執(zhí)行過程中,如果希望更改文本標(biāo)簽的顯示內(nèi)容,可以通過set_text()方法重新渲染文本圖像,并且更新矩形區(qū)域。根據(jù)Label類的類圖,在game_items模塊中定義一個繼承pygame.sprite.Sprite的Label類,具體代碼如下:11.5.3使用精靈實現(xiàn)文本標(biāo)簽classLabel(pygame.sprite.Sprite):"""文本標(biāo)簽精靈"""font_path="./res/font/MarkerFelt.ttc"#字體文件路徑

def__init__(self,text,size,color,*groups):super().__init__(*groups)self.font=pygame.font.Font(self.font_path,size)self.color=colorself.image=self.font.render(text,True,self.color)self.rect=self.image.get_rect()defset_text(self,text):self.image=self.font.render(text,True,self.color)self.rect=self.image.get_rect()2.創(chuàng)建指示器面板的文本標(biāo)簽精靈在HUDPanel類的構(gòu)造方法末尾創(chuàng)建指示器面板的文本標(biāo)簽精靈,代碼如下:11.5.3使用精靈實現(xiàn)文本標(biāo)簽#創(chuàng)建文本標(biāo)簽精靈#分?jǐn)?shù)標(biāo)簽self.score_label=Label("%d"%self.score,32,self.gray,display_group)self.score_label.rect.midleft=(self.status_sprite.rect.right+self.margin,self.status_sprite.rect.centery)#炸彈標(biāo)簽self.bomb_label=Label("X3",32,self.gray,display_group)self.bomb_label.rect.midleft=(self.bomb_sprite.rect.right+self.margin,self.bomb_sprite.rect.centery)......#提示標(biāo)簽self.tip_label=Label("Pressspacebartoplayagain.",22,self.white,display_group)self.tip_label.rect.midtop=(self.best_label.rect.centerx,self.best_label.rect.bottom+8*self.margin)在設(shè)定文本標(biāo)簽精靈的位置時,既可以參照之前的游戲示意圖,依次根據(jù)選好的每一個標(biāo)簽精靈的參照物設(shè)定,也可以每設(shè)置一次標(biāo)簽精靈的位置后進行運行測試,以確保每個標(biāo)簽精靈能顯示到正確的位置。運行游戲,可以在游戲窗口的左上、左下以及右下方位置看到圖像對應(yīng)的文本標(biāo)簽,如圖所示。11.5.3使用精靈實現(xiàn)文本標(biāo)簽需要注意的是,此時的指示器面板存在以下一些問題:游戲得分、炸彈計數(shù)、生命計數(shù)的數(shù)據(jù)不會變化;最好成績始終為0;提示信息不會隨著游戲狀態(tài)的變化而變化,而是始終顯示在游戲窗口中央位置。

先定一個小目標(biāo)!11.5.4顯示和修改游戲數(shù)據(jù)掌握顯示和修改游戲數(shù)據(jù),能夠?qū)崿F(xiàn)顯示和修改游戲數(shù)據(jù)11.5.4顯示和修改游戲數(shù)據(jù)HUDPanel類封裝了3個方法:show_bomb()、show_lives()、increase_score(),分別實現(xiàn)顯示炸彈數(shù)量、顯示生命計數(shù)、增加游戲得分的功能,下面依次實現(xiàn)這幾個功能。1.顯示炸彈數(shù)量根據(jù)游戲介紹,英雄飛機出場后默認會攜帶3顆炸彈,且會在玩家按下b鍵時引爆炸彈。引爆炸彈后,游戲窗口左下角的炸彈數(shù)量會減少。為了測試游戲是否能夠正常監(jiān)聽b鍵的事件,這里先以隨機數(shù)為例實現(xiàn)顯示炸彈數(shù)量的功能,即玩家按下b鍵后顯示隨機的炸彈數(shù)量。首先,在HUDPanel類中實現(xiàn)show_bomb()方法,通過show_bomb()方法的參數(shù)更新炸彈計數(shù)標(biāo)簽的顯示,具體代碼如下:defshow_bomb(self,count):#設(shè)置炸彈標(biāo)簽文字

self.bomb_label.set_text("X%d"%count)#設(shè)置炸彈標(biāo)簽位置

self.bomb_label.rect.midleft=(self.bomb_sprite.rect.right+self.margin,self.bomb_sprite.rect.centery)11.5.4顯示和修改游戲數(shù)據(jù)然后,在game模塊的頂部導(dǎo)入random模塊,代碼如下:importrandom11.5.4顯示和修改游戲數(shù)據(jù)最后,在Game類的event_handler()方法中添加代碼,監(jiān)聽玩家按下b鍵的事件,并使用隨機數(shù)測試顯示的炸彈數(shù)量,具體如加粗代碼所示:defevent_handler(self):……elifevent.type==pygame.KEYDOWNandevent.key==pygame.K_SPACE:ifself.is_game_over:#游戲已經(jīng)結(jié)束

self.reset_game()else:#切換暫停狀態(tài)

self.is_pause=notself.is_pauseifnotself.is_game_overandnotself.is_pause:#判斷是否正在游戲

#監(jiān)聽玩家按下字母b,引爆炸彈

ifevent.type==pygame.KEYDOWNandevent.key==pygame.K_b:self.hud_panel.show_bomb(random.randint(0,100))returnFalse11.5.4顯示和修改游戲數(shù)據(jù)運行游戲,游戲窗口左側(cè)顯示的炸彈數(shù)量為3,按下b鍵,炸彈數(shù)量變?yōu)?0,再次按下b鍵,炸彈數(shù)量變?yōu)?1。游戲窗口左下角炸彈數(shù)量的變化情況如圖所示。游戲窗口左下角炸彈數(shù)量的變化情況11.5.4顯示和修改游戲數(shù)據(jù)2.顯示生命計數(shù)按照游戲介紹,英雄飛機被敵機撞毀后,游戲窗口右下角的生命計數(shù)應(yīng)該相應(yīng)減少;英雄飛機每得到10萬分會被獎勵1條命,游戲窗口右下角的生命計數(shù)應(yīng)該相應(yīng)增加。為了測試游戲是否能夠正常顯示生命計數(shù),這里先以隨機數(shù)為例實現(xiàn)顯示生命計數(shù)的功能,即玩家按下b鍵后顯示隨機的生命計數(shù),具體步驟如下。在HUDPanel類中定義show_lives()方法,使用生命計數(shù)屬性值更新生命計數(shù)標(biāo)簽的顯示,代碼如下:defshow_lives(self):"""顯示生命計數(shù)"""self.lives_label.set_text("X%d"%self.lives_count)#設(shè)置生命計數(shù)標(biāo)簽文字

#設(shè)置生命計數(shù)標(biāo)簽位置

self.lives_label.rect.midright=(SCREEN_RECT.right-self.margin,self.bomb_label.rect.centery)#調(diào)整生命計數(shù)精靈位置

self.lives_sprite.rect.right=self.lives_label.rect.left-self.margin11.5.4顯示和修改游戲數(shù)據(jù)2.顯示生命計數(shù)修改Game類的event_handler()方法,在監(jiān)聽到玩家按下b鍵的事件處理中,使用隨機數(shù)測試生命計數(shù)的顯示,代碼如下:#判斷是否正在游戲ifnotself.is_game_overandnotself.is_pause:#監(jiān)聽玩家按下字母b,引爆炸彈

ifevent.type==pygame.KEYDOWNandevent.key==pygame.K_b:#TODO測試炸彈數(shù)量變化

self.hud_panel.show_bomb(random.randint(0,100))#TODO測試生命計數(shù)數(shù)量變化

self.hud_panel.lives_count=random.randint(0,10)self.hud_panel.show_lives()運行游戲,按下b鍵,可以在游戲窗口的右下角位置看到生命計數(shù)的變化。11.5.4顯示和修改游戲數(shù)據(jù)3.增加游戲得分根據(jù)游戲介紹,每當(dāng)英雄飛機摧毀一架敵機之后,游戲得分應(yīng)該相應(yīng)增加,且根據(jù)摧毀的敵機類型增加相應(yīng)的分值。需要注意的是,隨著游戲分?jǐn)?shù)的增加,其他游戲?qū)傩钥赡軙艿接绊懀ㄉ嫈?shù)、最好成績和游戲級別,具體如下。(1)生命計數(shù)。英雄飛機每得到10萬分會被獎勵1條命。(2)最好成績。若當(dāng)前游戲得分超過了歷史最好成績,將當(dāng)前的游戲得分設(shè)置為最好成績。(3)游戲級別。當(dāng)前游戲得分超過了級別預(yù)設(shè)的分?jǐn)?shù)后,會自動進入下一級別。級別不同,游戲中敵機的類型、數(shù)量和速度不同。11.5.4顯示和修改游戲數(shù)據(jù)在增加游戲得分時,除了要完成根據(jù)摧毀敵機的分值增加游戲得分的功能之外,還需處理與之相關(guān)的生命計數(shù)、最好成績以及游戲級別。下面分步驟實現(xiàn)這些功能。首先,在HUDPanel類的構(gòu)造方法上方定義幾個類屬性,方便后續(xù)計算獎勵生命和游戲級別,具體代碼如下:reward_score=100000#獎勵分值level2_score=10000#級別2分值level3_score=50000#級別3分值11.5.4顯示和修改游戲數(shù)據(jù)然后,在HUDPanel類中實現(xiàn)increase_score()方法,用于增加游戲得分,并處理與分?jǐn)?shù)有關(guān)的生命計數(shù)、最好成績以及游戲級別,具體代碼如下:defincrease_score(self,enemy_score):score=self.score+enemy_score#游戲得分ifscore//self.reward_score!=self.score//self.reward_score:self.lives_count+=1self.show_lives()self.score=scoreself.best_score=scoreifscore>self.best_scoreelseself.best_score......self.score_label.rect.midleft=(self.status_sprite.rect.right+self.margin,self.status_sprite.rect.centery)returnis_upgrade11.5.4顯示和修改游戲數(shù)據(jù)最后,在Game類的游戲循環(huán)中增加測試increase_score()方法的代碼,具體如下:else:#TODO測試修改游戲得分

ifself.hud_panel.increase_score(100):print("升級到%d"%self.hud_panel.level)#更新all_group中所有精靈內(nèi)容

self.all_group.update()11.5.4顯示和修改游戲數(shù)據(jù)運行游戲,可以看到游戲窗口左上角的分?jǐn)?shù)標(biāo)簽快速地發(fā)生變化,達到獎勵分?jǐn)?shù)后,游戲窗口右下角的生命計數(shù)數(shù)值增加,如圖所示。

先定一個小目標(biāo)!11.5.5保存和顯示最好成績掌握保存和顯示最好成績,能夠?qū)崿F(xiàn)保存和顯示最好成績最好成績是一個永久記錄,不會因為游戲的退出而丟失,因此需要進行持久化存儲??紤]到最好成績占據(jù)的數(shù)據(jù)量比較小,可以直接采用文件存儲方式。在HUDPanel類的類圖中,設(shè)計了save_best_score()和load_best_score()方法,分別用于保存和加載最好成績。下面分別實現(xiàn)save_best_score()方法和load_best_score()方法,并在適當(dāng)?shù)奈恢谜{(diào)用這兩個方法,以保存和顯示最好成績。11.5.5保存和顯示最好成績1.保存最好成績首先,在HUDPanel類的構(gòu)造方法上方定義一個類屬性,使用該屬性指定保存最好成績的文件名,代碼如下:record_filename="record.txt"#最好成績文件名11.5.5保存和顯示最好成績?nèi)缓?,在HUDPanel類中實現(xiàn)save_best_score()方法,代碼如下:defsave_best_score(self):"""將最好成績寫入record.txt"""file=open(self.record_filename,"w")file.write("%d"%self.best_score)file.close()最后,修改Game類的游戲循環(huán),在游戲退出之前,調(diào)用指示器面板的save_best_score()方法,修改后的代碼如加粗部分所示:defstart(self):"""開始游戲"""……ifself.event_handler(): #事件監(jiān)聽

self.hud_panel.save_best_score()return……11.5.5保存和顯示最好成績運行游戲,等到游戲分?jǐn)?shù)增長到一定數(shù)值后,按下ESC鍵退出游戲,此時可以看到飛機大戰(zhàn)項目目錄下新建了record.txt文件,record.txt文件中保存了游戲退出時記錄的分?jǐn)?shù),如圖所示。11.5.5保存和顯示最好成績2.加載最好成績游戲結(jié)束后會在窗口中央顯示最好成績,因此我們需要從record.txt文件中加載最好成績。在HUDPanel類中實現(xiàn)load_best_score()方法,代碼如下:11.5.5保存和顯示最好成績defload_best_score(self):"""從record.txt加載最好成績"""try:file=open(self.record_filename)txt=file.readline()file.close()self.best_score=int(txt)except(FileNotFoundError,ValueError):print("文件不存在或者類型轉(zhuǎn)換錯誤")修改HUDPanel類的構(gòu)造方法,在定義完游戲?qū)傩灾螅{(diào)用load_best_score()方法加載最好成績,修改后的代碼如下所示:11.5.5保存和顯示最好成績def__init__(self,display_group):"""構(gòu)造方法

:paramdisplay_group:面板中的精靈要被添加到的顯示精靈組

"""#游戲?qū)傩?/p>

self.score=0 #游戲得分

self.lives_count=3 #生命計數(shù)

self.level=1 #游戲級別

self.best_score=0 #最好成績

self.load_best_score() #加載最好成績

……運行游戲,可以看到游戲窗口中央位置顯示了之前保存的最好成績,如圖所示。11.5.5保存和顯示

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論