<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML'></script>html
一般來講,Python解釋執行,運行速度慢,並不適合完整的開發遊戲。隨着電腦速度的快速提升,這種狀況有所好轉,但開發遊戲仍然不是Python的重點工做。
大多應用是利用Python開發效率高的特色,進行遊戲原型驗證,或者在大的遊戲系統中,使用Python進行地圖、場景等定製。還有就是使用遊戲開發的技術和理念,將Python用於商業視覺展現、工程效果展現。python
原型驗證:指的是有了一個好的遊戲想法,完整的開發出來確定須要大量的人員、費用、時間,利用Python編程簡單高效的特色,先模擬完成一部分遊戲的功能,從而可以展現給投資人、客戶,獲取你們的承認,進而獲得經費投入。
地圖、場景定製:遊戲的開發確定須要不少專業技術方面的高精尖人才,但遊戲的運營、地圖的設計、故事情節等。這都是商業或者藝術方面的專業強項,而這些人員不大可能使用c/c++等經常使用的遊戲開發工具來作這些工做。所以,遊戲開發過程當中,一般完成Python語言的接口,讓這些商業、藝術工做人員也能使用比較方便的手段進行遊戲功能的調整。c++
此外,現代的遊戲開發已是一個大團隊合做的產物,已經很是難以單打獨鬥完成一款遊戲。因此學習遊戲編程的目標並非但願本身獨立完成一個遊戲,而是用這種思路來解決具體問題。
一般遊戲開發的工做分工是這樣的:
其中音效、畫面都會由更專業的團隊完成。最後由程序人員集成在遊戲中。在遊戲中,音樂音效、操做控制、遊戲邏輯、畫面幾個部分,都是並行在同時進行的。它們必須共同生效,遊戲纔會好玩。ajax
Pygame是一個強大的遊戲擴展包,首先也是安裝:編程
#使用管理員模式啓動cmd命令行,而後執行: pip install pygame #某些系統是pip3 install pygame
這個安裝擴展包的過程,咱們重複了不少遍,這個算是最後一遍了。由於Pygame是咱們課程講解的最後一個擴展包。比起來其它的軟件,Python的擴展包,只要你知道了名字,安裝幾乎都是相同的。即使不一樣的操做系統,差異也不大。flask
在這一講,咱們會採用跟之前不一樣的方法來說述Pygame擴展包的使用。緣由是Python有很是多的擴展包。即使官方內置的擴展包,也量很是大。若是徹底等待別人教你使用這種方式是不可能的,此外即使是別人教過了,Python和擴展包的升級也很是的快。原有的使用方法,極可能如今已經不適用了。這些都要求你有本身探索的能力,在Python基本技能的學習掌握以後,根據本身的編程需求,選擇相應的擴展包,查找資料、文檔。在網上資料的幫助下,掌握擴展包的使用方法。網絡
從目前行業內的使用狀況看,最大的障礙在於目前主要的文檔來源都是英文的,這要求咱們具有必定的英文閱讀能力。此外,雖然版本的更新對擴展包的使用有一些差異,但這種差異畢竟不算大。因此在國內一些相對較早的文檔幫助下,再對應國外新版本的文檔,也能下降你的學習門檻。架構
只是播放mp3,Python有不少擴展包能夠選,不少操做起來也更簡便。不過pygame是爲了遊戲設計,除了背景音樂,音效、與畫面的協做也考慮的更多。因此雖然用起來複雜一些,咱們依然仍是選擇學習用Pygame播放mp3音樂。目的,更可能是指望學習者除了學習python相關的知識,也更多理解現代計算機併發多任務和多種約束條件下的編程思惟。併發
拿到一個新的擴展包,一般你有這樣幾種途徑瞭解它的使用:框架
到官網查看官方文檔(一般是英文)
在搜索引擎網站好比百度搜索中文的資料,這種狀況比較多見,由於大多狀況下,你之因此知道這個擴展包,也是在網上搜索相關資料的時候,別人介紹的。而一般這種狀況下,都已經有包簡單實用的介紹。
使用Python內置的dir()/help()函數,當前仍是英文資料,適合已經瞭解擴展包的基本架構,只是在函數選擇、調用的時候查找資料
因此,實際上,經過搜索引擎查找相關資料,應當是你上手的最優選擇。以pygame爲例,經過查找中文的資料,總結以後,應當能寫出這樣的程序:
#MP3播放器 #引入擴展庫 import pygame #歌曲文件 file='rongHua.mp3' #初始化聲音庫 pygame.mixer.init(frequency=44100) print("播放音樂-絨花") #載入音樂文件 pygame.mixer.music.load(file) #播放聲音 pygame.mixer.music.play()
程序每一條語句都有註釋,大概的框架上看,應當也是順序執行的。有一些參數可能你還不能明白,好比frequency=44100
,不過應當不影響你抄過來用。這個是指定音頻庫使用的採樣頻率,44100通常已是高保真音樂的採樣頻率了。一般mp3文件都是這種格式。另外忘了交代,rongHua.mp3是咱們要播放的聲音文件名稱,記得要提早準備好,放到程序同一個目錄。
執行程序以後發現,詭異的事情發生了,程序只顯示了一行文字:「播放音樂-絨花」,而後就退出了,並無事情發生,也沒有音樂播放出來。
一開始就說過了,本講重點不徹底是播放一首音樂,而是但願能引導你們使用探索的方式,來了解一個新的擴展包如何學習和使用。因此不要等待着我說出答案,而是積極的思考,判斷出現了什麼問題,而且嘗試去解決。
首先要說明的是,程序自己引入pygame庫、庫的初始化還有播放語句語句自己都並無什麼錯誤。一般在網上查找資料的時候,只要認真閱讀,比較容易保證這一點。難以立刻學會並應用到編程中的,是關於某個庫「架構」方面的內容,也就是影響程序結構方面的內容。若是以爲這句話比較抽象的話,你能夠回憶一下上一講咱們嘗試過的flask網絡編程框架。框架、架構,這兩個詞在這裏基本能夠劃等號了。
咱們的程序沒有能播放出來音樂,也是這方面的緣由。
一般遊戲程序要包含至少4部分的內容,咱們用本講開始的那張圖來講明,音樂、畫面、操控、邏輯這四部份內容是並行運行,相互配合,才能展示給用戶一個圖文並茂、流暢、吸引人的遊戲。
所以做爲遊戲的一部分,音樂的播放也不可能像咱們前面學過的繪圖、計算等操做同樣,在音樂沒有播放完成前,程序中止在那裏一直等待。事實上一般遊戲的作法都是,發出播放音樂的命令以後,命令自己立刻返回,讓程序有能力並行去處理按鍵輸入、繪圖等動做。
而在咱們上面的程序中,播放這個命令確定是發出去了,但沒有等音樂聲響起,程序就已經結束退出了。程序的結束退出將自動的釋放程序打開的各項資源,清理運行的痕跡,從而音樂也就不可能再放出來了。
這僅僅是咱們推測分析的結果,咱們來證實一下,方法就是在程序最後增長一行語句:
#程序等待5秒鐘 pygame.time.delay(1000*5)
使用這樣語句的目的是,若是咱們上面的推測成立,那確定要對程序作結構上的調整。這個工做量會比較大,因此咱們先使用簡單的語句來驗證一下咱們的思考。
再次運行程序,你會聽到音樂響了5秒鐘,而後程序退出,音樂也中止了。
這基本能夠證實,咱們的思考正確。此外彷佛還有些別的問題,好比音樂一開始有一個「破音」,這讓人感受很差。並且程序彷佛有的時候能正常播放,有的時候仍是不穩定,沒法播放成功。
下面要如何改進程序呢?
一般咱們會繼續在網上搜索pygame模塊使用的案例,閱讀別人的程序,有的時候運氣好,你碰到的程序代碼,跟你想寫的代碼是徹底相同的功能,這時候你能夠拷貝過來直接使用。但大多時候,你只能找到功能相近的代碼,因此仍然須要你閱讀別人的程序,並從其中學習對你有用的部分。
好比,你可能搜索到咱們第一講演示的遊戲,其中固然也有聲音處理的部分,你會重點閱讀這部分的代碼,來找出同本身程序的區別,以求解決問題。
在這個過程當中,咱們又作出了一些判斷,固然這些判斷依然須要大量程序的經驗,因此並不能要求初學者也能輕易作到。但複雜的作不到,你能夠從簡單的入手,逐漸積累。這裏只是想告訴你正確的學習思路:
驗證思考最好的辦法就是修改程序,而後再次運行實驗,所以咱們再完成一版程序:
#引入擴展庫 import pygame #歌曲文件 file='rongHua.mp3' #初始化pygame顯示庫 pygame.display.init() #打開一個窗口 screen = pygame.display.set_mode([200,100]) #初始化pygame聲音庫 pygame.mixer.init(frequency=44100) print("播放音樂-絨花") #載入音樂文件 pygame.mixer.music.load(file) #保存當前音量 v = pygame.mixer.music.get_volume() #設置爲靜音,防止開始的爆破音 pygame.mixer.music.set_volume(0) #播放聲音 pygame.mixer.music.play() #延時0.2秒打開聲音,避過爆破音 pygame.time.delay(200) pygame.mixer.music.set_volume(v) #播放5秒鐘 pygame.time.delay(1000*5) #中止播放 pygame.mixer.music.stop() #退出聲音庫和顯示庫 pygame.mixer.quit() pygame.display.quit()
每一行代碼都有註釋,我只講解跟上一版不一樣的代碼:
此外這些工做中,用到了不少新的函數,這些函數一開始你並不可能知道。這些函數的學習通常是兩個方向,一是概要的瀏覽pygame的手冊或者幫助,在心中有一個粗的概念,這樣用到什麼功能的時候,你會想起來可能有某個函數能完成這個功能,而後再精細查看。第二是但願用到某個功能,在網上查找使用Python或者pygame如何作到這個功能。固然還有另一種渠道,有可能你直接搜索到了功能相近的代碼,從中間直接抄過來使用。
試運行以後咱們開心的發現,穩定性問題和爆破音都解決了,剩下最關鍵的,如何完整的播放音樂文件?
這涉及到了咱們前面講過的程序結構問題,也是一個框架型的程序庫對程序結構的要求。這一部分通常沒有好辦法,只能經過閱讀官方的文檔或者閱讀其它程序的成熟代碼來獲取,這個過程通常會較長。好在咱們大多狀況下不會上來就碰到這麼複雜的問題,都是按部就班。而且大多的擴展包只是增長功能性的函數,並不要求程序的結構有多少改變。
咱們經過一張對比圖來講明pygame對程序結構的要求:
傳統程序雖然咱們不怎麼熟悉聲音處理,但結構咱們都比較熟悉。程序中可能有循環,但整體是串行執行的,完成一件事情,纔去作另一件。
從外觀上看,右側的遊戲程序結構,跟左側不過多了一個循環。但你要記得,這裏面每一項都是並行執行的,每個步驟並不會等待這一項工做作完,就會返回接受新的命令,因此程序的聲音、圖像、程序邏輯、鍵盤控制,纔可能一塊兒發生做用。
這種並行處理的程序,同傳統的程序比,有不少不可協調的理念區別,pygame爲了作到並行,採用了「事件驅動」的理念來完成這種控制。
事件驅動實際是存在好久的編程方式了,通常傳統的Windows程序,都使用微軟公司提供的消息循環,來處理全部的窗口事件。Python pygame的事件處理,也是採用相似的機制。
總結一下使用事件驅動的方式來編寫pygame程序的要點:
咱們根據剛纔這些理念,從新改寫程序,這個程序最終造成code4.py,這裏只介紹重點的消息循環部分:
#... 初始化及基本播放代碼忽略... #自定義一條消息(一個事件)用於表示播放結束 #pygame.USEREVENT是pygame中預約義的用戶消息起始值 MUSIC_END = pygame.USEREVENT + 1 #設置當前音樂播放完成後,發送自定義的消息 pygame.mixer.music.set_endevent(MUSIC_END) #延時0.2秒打開聲音,避過爆破音 pygame.time.delay(200) pygame.mixer.music.set_volume(v) #定義一個退出程序標誌 requireQuit = False #程序主循環 while not requireQuit: #循環接受各類事件 for event in pygame.event.get(): #若是是自定義的播放完成消息 if event.type == MUSIC_END: requireQuit=True #退出 break #界面窗口菜單關閉申請 elif event.type == pygame.QUIT: requireQuit=True break #有鍵盤擡起 elif event.type == pygame.KEYUP: #q鍵 if event.key == pygame.K_q: requireQuit=True break #... 退出操做 ...
程序中,咱們本身定義了一條消息。所謂消息,並非日常人類喜聞樂見的一條短信或者語音,其實就是一個整數數字。爲了容易記憶,咱們固然本身定義了一個變量名來表明它,但實際它就是一個數字。
緣由是對計算機來說,其實一切都是數字,咱們用一個字符串反而讓計算機執行的更慢。
隨後,由於咱們的消息循環中確定還可能嵌套循環,一個break語句只能打破內部的循環,並不能讓外部循環也退出,因此咱們定義了一個bool的變量,來表示程序是否須要退出循環。
這裏的消息循環從技術上並無啥難度,主要是你須要適應這麼多新的函數和預約義的變量(這裏固然當作常量來用,好比表示pygame須要退出)。
在內部循環中,咱們判斷了三種可能須要退出的消息。一是本身定義的,若是音樂播放結束,應當退出;二是用戶用鼠標關閉窗口,程序應當退出;三是按q鍵表示用戶但願退出播放。
按下按鍵遊戲採起相應動做是很常見的遊戲處理工做,咱們在這裏等待用戶按下按鍵而後再鬆開的這一刻退出,這樣防止用戶按下q鍵一直沒有鬆手所致使的程序退出後,屏幕上還會出現不少q字符的狀況。
如今的程序已經能正常的播放音樂了,實際上咱們的程序還能進一步優化。好比1.添加播放的時間顯示;2.向前向後跳轉播放。
這兩個功能均可以在消息循環中處理,這樣程序纔是並行的。如今你可能感受到了,實際上消息循環中,纔是程序的主要邏輯。的確如此,其實全部的遊戲基本都是在消息循環中作全部的主要工做,固然具體工做細節,都是由已經定義好的函數或叫子程序來具體執行完成的,在主循環中,只是對這些函數的組織、管理和調用。
顯示播放位置:
#程序主循環 while not requireQuit: #獲取當前播放位置 pos=pygame.mixer.music.get_pos() #顯示 print("Playing:", pos,end='\r')
消息循環中,在按鍵部分添加代碼:
#若是是向右鍵,則前跳10秒 elif event.key == pygame.K_LEFT: pygame.mixer.music.set_pos(pos/1000-10) #若是是向左鍵,則後跳10秒 elif event.key == pygame.K_RIGHT: pygame.mixer.music.set_pos(pos/1000+10)
這樣的功能增長,依賴於你對pygame擴展庫愈來愈熟悉,經過閱讀文檔,發現pygame擴展庫能提供什麼樣的功能。而這個功能你又須要,就能夠加入到程序中。
其實本講能夠說從開始到如今都是挑戰,所以沒有再設置單獨的挑戰環節。
咱們直接進入練習的環節:
請參考mp3Player.py程序。
(全部本系列中出現、使用過的源碼將會在連載完成後統一整理提供下載。)
原文出處:https://www.cnblogs.com/andrewwang/p/10208319.html