2017-09-28 59 views
1

我正在嘗試爲我的遊戲獲取背景音樂,但我似乎無法完全弄清楚它。我過去使用過pygame,但是在我的遊戲中有一首歌。 我希望播放列表隨機播放每首曲目。我已經成功地在一個單獨的測試文件中工作。我將在下面發佈此代碼。Pygame播放列表在後臺連拍

問題是當我在主遊戲中調用此函數時,音樂播放第一首曲目,然後停止。如果我放入

while pygame.mixer.music.get_busy(): 
    continue 

它只是播放音樂,不讓我玩遊戲。我希望它不斷循環通過播放列表,而用戶玩遊戲(這是一個基於文本的遊戲,所以它使用raw_input()很多

這裏是我的代碼:

import pygame 
import random 

pygame.mixer.init() 

_songs = [songs, are, here] 

_currently_playing_song = None 

def music(): 
    global _currently_playing_song, _songs 
    next_song = random.choice(_songs) 
    while next_song == _currently_playing_song: 
     next_song = random.choice(_songs) 
    _currently_playing_song = next_song 
    pygame.mixer.music.load(next_song) 
    pygame.mixer.music.play() 

while True: ## This part works for the test, but will not meet my needs 
    music() ## for the full game. 
    while pygame.mixer.music.get_busy(): 
     continue 

(PS我通過學會蟒蛇肖捷思銳的「學習Python辛苦」的,所以我的遊戲結構採用從書的引擎和地圖系統)

+0

[這是一個答案](https://stackoverflow.com/a/45597549/6220679),告訴你如何播放隨機歌曲,如果最後一首歌曲完成或按下右箭頭循環播放歌曲列表鍵。 – skrx

回答

2

您可以使用一個線程在後臺播放音樂。

import threading 
musicThread = threading.Thread(target=music) 
musicThread.start() 

如果你想在不關閉遊戲的情況下停止音樂,你應該殺死線程。

+1

這是沒有必要的,因爲pygame會自動爲音樂創建一個線程。 –

2

您可以設置一個pygame.mixer.music.set_endevent(),當音樂結束時它會在事件隊列中張貼。然後,你只需選擇另一首歌曲。沿着這些路線的東西:

import os 
import pygame 
pygame.init() 
pygame.mixer.init() 

SIZE = WIDTH, HEIGHT = 720, 460 
screen = pygame.display.set_mode(SIZE) 

MUSIC_ENDED = pygame.USEREVENT 
pygame.mixer.music.set_endevent(MUSIC_ENDED) 


BACKGROUND = pygame.Color('black') 


class Player: 

    def __init__(self, position): 
     self.position = pygame.math.Vector2(position) 
     self.velocity = pygame.math.Vector2() 

     self.image = pygame.Surface((32, 32)) 
     self.rect = self.image.get_rect(topleft=self.position) 

     self.image.fill(pygame.Color('red')) 

    def update(self, dt): 
     self.position += self.velocity * dt 
     self.rect.topleft = self.position 


def load_music(path): 
    songs = [] 
    for filename in os.listdir(path): 
     if filename.endswith('.wav'): 
      songs.append(os.path.join(path, filename)) 
    return songs 


def run(): 
    songs = load_music(path='/Users/Me/Music/AwesomeTracks') 

    song_index = 0 # The current song to load 
    pygame.mixer.music.load(songs[song_index]) 
    pygame.mixer.music.play() 
    song_index += 1 

    clock = pygame.time.Clock() 
    player = Player(position=(WIDTH/2, HEIGHT/2)) 

    while True: 
     dt = clock.tick(30)/1000 

     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       quit() 
      elif event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_a: 
        player.velocity.x = -200 
       elif event.key == pygame.K_d: 
        player.velocity.x = 200 
       elif event.key == pygame.K_w: 
        player.velocity.y = -200 
       elif event.key == pygame.K_s: 
        player.velocity.y = 200 
      elif event.type == pygame.KEYUP: 
       if event.key == pygame.K_a or event.key == pygame.K_d: 
        player.velocity.x = 0 
       elif event.key == pygame.K_w or event.key == pygame.K_s: 
        player.velocity.y = 0 
      elif event.type == MUSIC_ENDED: 
       song_index = (song_index + 1) % len(songs) # Go to the next song (or first if at last). 
       pygame.mixer.music.load(songs[song_index]) 
       pygame.mixer.music.play() 

     screen.fill(BACKGROUND) 

     player.update(dt) 
     screen.blit(player.image, player.rect) 

     pygame.display.update() 

run() 

所以實際的解決方案只是3部分

  1. 創建事件MUSIC_ENDED = pygame.USEREVENT
  2. 告訴pygame的發佈事件時,歌曲結束pygame.mixer.music.set_endevent(MUSIC_ENDED)
  3. 檢查事件在事件隊列 for event in pygame.event.get(): if event.type == MUSIC_ENDED:

然後你可以自由地做任何你想要的。

+0

@Macimoar這是正確的答案,你真的不需要'線程'。我不知道爲什麼其他人有更多的讚揚。您可以通過點擊複選標記來接受您最喜歡的答案,將此問題標記爲已解決。 – skrx

+0

此解決方案適用於播放列表重複播放,但它不允許我在播放音樂時播放遊戲(我只有一個閃爍的光標,並且音樂會繼續播放,直到我執行中斷)。我不確定爲什麼。 – Macimoar

+0

@Macimoar這個'run'函數有望成爲你主遊戲循環的一部分。自行運行此代碼只會反覆播放音樂。問題的實際解決方案是,只要音樂停止,您就可以將事件放入遊戲中的事件隊列中,以便您可以將歌曲更改爲適當的任何內容。 –