目錄java
昨天晚上研究了很久pygame的音樂混合器mixer,出了不少問題後最終成功,不過學習原本也不可能一路順風的嗎,下面我就來說一講我遇到的問題。python
# 導庫,需安裝 import pygame # 把路徑賦值分別給三個變量,以便以後加載。 music_file_path1 = "./sound/background.mp3" music_file_path2 = "./sound/background1.mp3" music_file_path3 = "./sound/dead.mp3" # 初始化混合器 pygame.mixer.init()
開始嘗試直接加載新的音樂,想着循環裏有調用play方法,是否是直接調用load方法修改路徑,就能播放其餘音樂了呢?git
# 加載初始背景音樂 pygame.mixer.music.load(music_file_path1) while True: pygame.mixer.music.play() if 死亡: # 切換死亡音樂 pygame.mixer.music.load(music_file_path3) for 檢測按鍵 if 按鍵: #重開遊戲,並切換成初始背景音樂 pygame.mixer.music.load(music_file_path1) if 達成條件進入第二關: # 切換爲第二關背景音樂 pygame.mixer.music.load(music_file_path2) # 延時50ms以後進入下層循環 pygame.time.delay(50)
失敗、、、沒有完成切換音樂,只有播放初始音樂,切換的部分是靜音的。github
是否是能夠考慮多開幾個線程呢?以前java我就這麼搗鼓過,這個算是寫的比較亂的,主要仍是不懂的太多。多線程
# 導庫,系統自帶的。 import threading # 定義一個函數以便線程來執行。 def bgm(music_file_path): pygame.mixer.music.load(music_file_path) pygame.mixer.music.play() ... # 新建3個子線程 thread1 = threading.Thread(bgm(music_file_path1)) thread2 = threading.Thread(bgm(music_file_path2)) thread3 = threading.Thread(bgm(music_file_path3)) # 啓動線程1 thread1.strat() while True: if 死亡: # 切換死亡音樂 thread3.strat() for 檢測按鍵 if 按鍵: #重開遊戲,並切換成初始背景音樂 thread1.strat() if 達成條件進入第二關: # 切換爲第二關背景音樂 thread2.strat() # 延時50ms以後進入下層循環 pygame.time.delay(50)
一樣失敗了,剛開始,運行的就是死亡時候的背景音樂,也就是說,只有最後加載的那個起做用了,在具體點說,此時的thread1, thread2, thread3已是徹底相同的了。併發
加了許多改變,bgm函數里加了初始化mixer,線程改成了在循環裏運行匿名線程。(由於直接在循環裏thread1.start()的話,會報錯,說線程只能啓動一次。)函數
# 導庫,系統自帶的。 import threading # 定義一個函數以便線程來執行。 def bgm(music_file_path): pygame.mi pygame.mixer.music.load(music_file_path) pygame.mixer.music.play() ... while True: # 默認音樂 threading.Thread(bgm(music_file_path1)).start() if 死亡: # 切換死亡音樂 threading.Thread(bgm(music_file_path3)).start() for 檢測按鍵 if 按鍵: #重開遊戲,並切換成初始背景音樂 threading.Thread(bgm(music_file_path1)).start() if 達成條件進入第二關: # 切換爲第二關背景音樂 threading.Thread(bgm(music_file_path2)).start() # 延時50ms以後進入下層循環 pygame.time.delay(50)
如今看也以爲怎麼看怎麼錯的,不過這卻是給我提供了一個思路,只要每次切換音樂的時候從新初始化一下mixer就能播放新的了。學習
嘗試不止三次,我只是找了3個可能比較有表明性的例子,但願你們能從中吸收經驗,下面,我將展現成功的代碼。測試
# 定義3個變量來表示是否在播放哪首音樂。 sound1, sound2, sound3 = True, True, True # 加載初始背景音樂 pygame.mixer.music.load(music_file_path1) pygame.mixer.music.play() while True: if 死亡: # 切換死亡音樂 # 經過sound的True, False的值的改變,控制只有第一次進入這個判斷條件的時候纔會初始化混合器。防止出現每50ms加載一次音樂的開頭50ms的狀況。 if sound3: pygame.mixer.init() pygame.mixer.music.load(music_file_path3) sound3 = False sound1, sound2 = True, True if pygame.mixer.get_busy != 1: pygame.mixer.music.play() for 檢測按鍵 if 按鍵: #重開遊戲,並切換成初始背景音樂 if sound1: pygame.mixer.init() pygame.mixer.music.load(music_file_path1) sound1 = False sound2, sound3 = True, True if pygame.mixer.get_busy != 1: pygame.mixer.music.play() if 達成條件進入第二關: # 切換爲第二關背景音樂 if sound2: pygame.mixer.init() pygame.mixer.music.load(music_file_path1) sound2 = False sound1, sound3 = True, True if pygame.mixer.get_busy != 1: pygame.mixer.music.play() # 延時50ms以後進入下層循環 pygame.time.delay(50)
最終成功!線程
這個其實挺簡單的,就是我開始的時候被坑了,被坑的緣由如今也不太清楚。。
# 飛機的發射子彈類 def launch_bullet: sound = pygame.mixer.Sound("./sound/bullet.wav") sound.play() # 敵機的被擊毀判斷 if 敵機被擊毀: sound = pygame.mixer.Sound("./sound/boom.wav") sound.play()
真的很簡單的啊,就這樣就應該能夠了啊,結果它報錯了,說unable to open file "./sound/bullet.wav",無奈,只能換方法。。
通過查閱發現了winsound這個模塊,而後,testing...
# 導入模塊,系統自帶的 import winsound # 飛機的發射子彈類 def launch_bullet: winsound.PlaySound("./sound/bullet.wav", SND_NOSTOP) # 敵機的被擊毀判斷 if 敵機被擊毀: winsound.PlaySound("./sound/boom.wav", SND_NOSTOP)
而後成功感覺到了單線程的惡意。。。
因而就用多線程吧,結合java的經驗,必定手到擒來的吧!
# 再次嘗試使用threading import threading import winsound # 飛機的發射子彈類 def launch_bullet: # 直接匿名函數先測試走起! threading.Thread(winsound.PlaySound("./sound/bullet.wav", SND_NOSTOP)).start() # 敵機的被擊毀判斷 if 敵機被擊毀: threading.Thread(winsound.PlaySound("./sound/boom.wav", SND_NOSTOP)).start()
有點錯愕地發現失敗了,跟以前一次的嘗試結果同樣,而後才知道原來python的多線程由於什麼緣由我忘了,仍是順序執行的。
在網上了解到了多進程能夠實現併發訪問,因而
# 系統自帶 import multiprocessing import winsound # 飛機的發射子彈類 def launch_bullet: multiprocessing.freeze__support() p = multiprocessing.Process(winsound.PlaySound("./sound/bullet.wav", SND_NOSTOP)) p.start() # 敵機的被擊毀判斷 if 敵機被擊毀: multiprocessing.freeze__support() p = multiprocessing.Process(winsound.PlaySound("./sound/boom.wav", SND_NOSTOP)) p.start()
而後每射一發子彈,就給我打開一個新窗口,我。。。。
最後決定仍是再給Sound一個機會,他文檔上不是說只能加載wav和ogg嗎?wav失敗了,我再從新找一下ogg的素材吧。而後就成功了。就成功了。。。我搗鼓半天,結果是素材的緣由。
# 飛機的__init__方法裏 self.sound = pygame.mixer.Sound("./sound/bullet.ogg") # 飛機的發射子彈類 def launch_bullet: self.sound.play() # 敵機的__init__方法裏 self.sound = pygame.mixer.Sound("./sound/get_score.ogg") # 敵機的被擊毀判斷 if 敵機被擊毀: self.sound.play()
具體第一次嘗試爲什麼失敗咱們仍未可知,也許是文件太大了?
真的是一次印象挺深入的經歷,深入到我這篇全文都是沒看以前的代碼敲出來的,甚至學了個新單詞mixer是混合器的意思。程序源碼我會放在個人github上。