2017-09-28 13 views
1

J'essaie d'obtenir de la musique de fond pour mon jeu, mais je n'arrive pas à le comprendre parfaitement. J'ai utilisé pygame dans le passé, mais c'était seulement pour une chanson au générique de mon jeu. Je souhaite que la liste de lecture soit lue en continu en sélectionnant chaque piste de manière aléatoire. J'ai réussi à obtenir ce travail dans un fichier de test distinct. Je vais poster ce code ci-dessous. Le problème est lorsque j'appelle cette fonction dans mon jeu principal, la musique joue la première piste, puis s'arrête. Si je metsPygame Playlist Continue en arrière-plan

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

Il joue juste la musique et ne me laisse pas jouer le jeu. Je veux le lire en boucle à travers la liste de lecture pendant que l'utilisateur joue le jeu (c'est un jeu basé sur le texte de sorte qu'il utilise raw_input() beaucoup

Voici mon code:.

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 j'appris python par Zed "Apprendre Python The Hard Way" Shaw est si ma structure de jeu utilise le système de moteur et carte du livre)

+0

[Voici une réponse] (https://stackoverflow.com/a/45597549/6220679) qui vous montre comment lire une chanson aléatoire si la dernière est terminée ou parcourir une liste de chansons en appuyant sur la flèche droite clé. – skrx

Répondre

2

Vous pouvez utiliser un fil pour jouer de la musique en arrière-plan.

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

Si jamais vous voulez arrêter la musique sans fermer votre jeu, vous devriez tuer le fil.

+1

Ceci n'est pas nécessaire puisque pygame crée automatiquement un fil pour la musique. –

2

Vous pouvez définir un pygame.mixer.music.set_endevent() qui est publié dans la file d'attente d'événements lorsque la musique est terminée. Ensuite, vous choisissez simplement une autre chanson. Quelque chose le long de ces lignes:

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() 

Donc, la solution réelle est à seulement 3 parties

  1. Créer un événement MUSIC_ENDED = pygame.USEREVENT.
  2. Dites pygame pour poster l'événement quand une chanson se termine pygame.mixer.music.set_endevent(MUSIC_ENDED)
  3. Vérifier l'événement dans la file d'attente d'événements for event in pygame.event.get(): if event.type == MUSIC_ENDED:

Et puis vous êtes libre de faire ce que vous désirez.

+0

@Macimoar C'est la bonne réponse et vous n'avez vraiment pas besoin de "threading". Je ne sais pas pourquoi l'autre a plus de votes. Vous pouvez accepter votre réponse préférée en cliquant sur la coche pour marquer cette question comme résolue. – skrx

+0

Cette solution fonctionne bien pour que la liste de lecture se répète, mais elle ne me permet pas de jouer pendant que la musique joue (je n'ai qu'un curseur clignotant et la musique continue à jouer jusqu'à ce que je fasse une interruption). Je ne suis pas sûr exactement pourquoi cependant. – Macimoar

+0

@Macimoar Cette fonction 'run' devrait faire partie de votre boucle de jeu principale. Exécuter ce code par lui-même ne fera rien de plus que de jouer de la musique à plusieurs reprises. La solution réelle au problème est que vous mettez des événements dans la file d'attente des événements dans votre jeu à chaque fois que la musique s'arrête pour que vous puissiez changer la chanson selon ce qui est approprié. –