mp3 und Midi in pygame abspielen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
grtur
User
Beiträge: 3
Registriert: Donnerstag 14. April 2022, 03:54
Wohnort: Münster/Westfalen

Hallo, liebe Gemeinde! :lol:
Ich lerne gerade Pythonprogrammierung im Selbststudium (nur aus Spaß und Interesse). Jetzt habe ich ein Spiel programmiert, in dem in pygame auch Soundeffekte abgespielt werden sollen. Mit wav-Dateien klappt es hervorragend. Nur bei mp3- und midi-Dateien bekomme ich Probleme. Die folgenden Zeilen spielen den Sound ab:

pickUpSound = pygame.mixer.Sound('pickup.wav')
pygame.mixer.music.load('background.mid')
pygame.mixer.music.play(-1, 0.0)
musicPlaying = True

Wenn das Programm so wie oben abläuft, fängt es kurz an und stürzt dann unvermittelt ab. Wenn ich die Zeile "pygame.mixer.music.play(-1, 0.0)" auskommentiere, läuft das Programm. Auch wenn ich die mid-Datei durch eine wav-Datei ersetze funktioniert es.

Das Gesamtprogramm stammt aus einem Lehrbuch und entspricht zu 100-% dem Programm aus dem Buch. Es gibt dort ein onlinetool, mit dem das Original und das selbst geschriebene Programm verglichen werden können und es wird kein Fehler angezeigt.

Bei mp3-Dateien bekomme ich folgende Fehlermeldung: "pygame.error: Failed loading libmpg123-0.dll: ", und zwar auch, wenn die ...play-Zeile auskommentiert ist.

Da ich nun seit ein paar Tagen versuche, das Problem zu lösen: H I L F E !!!!

Und schon mal meinen aller herzlichsten Dank im Voraus für hilfreiche Tips.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Moin,

nur anhand dieses Codeschnipsels können wir nicht verorten wo das Problem liegt.
Der Absturz wird mit hoher Wahrscheinlichkeit nicht an diesen 4 Zeilen liegen.
Du musst uns schon das ganze Programm zeigen und dazu bitte den "Vollständigen Editor" und darin die Code-Tags </> benutzen.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der zweite Fehler ist relativ offensichlich: der notwendige Decoder fuer MP3 fehlt. Ich benutze pygame nicht unter Windows, aber ggf. muss da etwas extra installiert werden, oder deine Installation ist kaputt.

Und das waere auch meine generelle Vermutung. Das ein MIDI-File beim abspielen einen harten Absturz produziert, ist ungewoehnlich.
grtur
User
Beiträge: 3
Registriert: Donnerstag 14. April 2022, 03:54
Wohnort: Münster/Westfalen

OK. Hier ist das komplette Programm. Geschrieben mit der IDLE.
Schon mal vielen Dank für Deine Mühe!


import pygame, sys, time, random
from pygame.locals import *

# Set up pygame.
pygame.init()
mainClock = pygame.time.Clock()

# Set up the window.
WINDOWWIDTH = 400
WINDOWHEIGHT = 400
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Sprites and Sounds')

# Set up the colors.
WHITE = (255, 255, 255)

# Set up the block data structure.
player = pygame.Rect(300, 100, 40, 40)
playerImage = pygame.image.load('player.png')
playerStretchedImage = pygame.transform.scale(playerImage, (40, 40))
foodImage = pygame.image.load('cherry.png')
foods = []
for i in range(20):
foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - 20), random.randint(0, WINDOWHEIGHT - 20), 20, 20))

foodCounter = 0
NEWFOOD = 40

# Set up keyboard variables.
moveLeft = False
moveRight = False
moveUp = False
moveDown = False

MOVESPEED = 6

# Set up the music.
pickUpSound = pygame.mixer.Sound('pickup.wav')
pygame.mixer.music.load('starwars.mp3')
#pygame.mixer.music.play(-1, 0.0)
musicPlaying = True

# Run the game loop.
while True:
# Check for the QUIT event.
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
# Change the keyboard variables.
if event.key == K_LEFT or event.key == K_a:
moveRight = False
moveLeft = True
if event.key == K_RIGHT or event.key == K_d:
moveLeft = False
moveRight = True
if event.key == K_UP or event.key == K_w:
moveDown = False
moveUp = True
if event.key == K_DOWN or event.key == K_s:
moveUp = False
moveDown = True
if event.type == KEYUP:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_LEFT or event.key == K_a:
moveLeft = False
if event.key == K_RIGHT or event.key == K_d:
moveRight = False
if event.key == K_UP or event.key == K_w:
moveUp = False
if event.key == K_DOWN or event.key == K_s:
moveDown = False
if event.key == K_x:
player.top = random.randint(0, WINDOWHEIGHT - player.height)
player.left = random.randint(0, WINDOWWIDTH - player.width)
if event.key == K_m:
if musicPlaying:
pygame.mixer.music.stop()
else:
pygame.mixer.music.play(-1, 0.0)
musicPlaying = not musicPlaying

if event.type == MOUSEBUTTONUP:
foods.append(pygame.Rect(event.pos[0] - 10, event.pos[1] - 10, 20, 20))

foodCounter += 1
if foodCounter >= NEWFOOD:
# Add new food.
foodCounter = 0
foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - 20), random.randint(0, WINDOWHEIGHT - 20), 20, 20))

# Draw the white background onto the surface.
windowSurface.fill(WHITE)

# Move the player.
if moveDown and player.bottom < WINDOWHEIGHT:
player.top += MOVESPEED
if moveUp and player.top > 0:
player.top -= MOVESPEED
if moveLeft and player.left > 0:
player.left -= MOVESPEED
if moveRight and player.right < WINDOWWIDTH:
player.right += MOVESPEED


# Draw the block onto the surface.
windowSurface.blit(playerStretchedImage, player)

# Check whether the block has intersected with any food squares.
for food in foods[:]:
if player.colliderect(food):
foods.remove(food)
player = pygame.Rect(player.left, player.top, player.width + 2, player.height + 2)
playerStretchedImage = pygame.transform.scale(playerImage, (player.width, player.height))
if musicPlaying:
pickUpSound.play()

# Draw the food.
for food in foods:
windowSurface.blit(foodImage, food)

# Draw the window onto the screen.
pygame.display.update()
mainClock.tick(40 )
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Ich habe deinen Code mal etwas angepasst und eigene Bilder und Sounds genommen.

So läuft es bei mir ohne Fehler.

Code: Alles auswählen

import pygame, time, random
from pygame.locals import *

WINDOWWIDTH = 400
WINDOWHEIGHT = 400
WHITE = (255, 255, 255)
NEWFOOD = 40
MOVESPEED = 6

class Game():
    # Set up pygame.
    def __init__(self):
        self.main_clock = pygame.time.Clock()

        # Set up the window.
        self.window_surface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
        pygame.display.set_caption('Sprites and Sounds')

        # Set up the block data structure.
        self.player = pygame.Rect(300, 100, 40, 40)
        self.player_image = pygame.image.load('player.png')
        self.player_stretched_image = pygame.transform.scale(self.player_image, (40, 40))
        self.food_image = pygame.image.load('berry.png')

        self.foods = [pygame.Rect(random.randint(0, WINDOWWIDTH - 20),
                                  random.randint(0, WINDOWHEIGHT - 20),20, 20)
                      for _ in range(20)
                     ]
        self.food_counter = 0

        # Set up keyboard variables.
        self.move_left = False
        self.move_right = False
        self.move_up = False
        self.move_down = False
        
        self.init_music()

    def init_music(self):
        # Set up the music.
        self.pickup_sound = pygame.mixer.Sound('pickup.wav')
        pygame.mixer.music.load('background.mp3')
        pygame.mixer.music.play(-1, 0.0)
        self.music_playing = True
    
    def run(self):
        # Run the game loop.
        run_loop = True
        while run_loop:
            # Check for the QUIT event.
            for event in pygame.event.get():
                if event.type == QUIT:
                    run_loop = False
                    break
                if event.type == KEYDOWN:
                    # Change the keyboard variables.
                    if event.key == K_LEFT or event.key == K_a:
                        self.move_right = False
                        self.move_left = True
                    if event.key == K_RIGHT or event.key == K_d:
                        self.move_left = False
                        self.move_right = True
                    if event.key == K_UP or event.key == K_w:
                        self.move_down = False
                        self.move_up = True
                    if event.key == K_DOWN or event.key == K_s:
                        self.move_up = False
                        self.move_down = True
                if event.type == KEYUP:
                    if event.key == K_ESCAPE:
                        run_loop = False
                        break
                    if event.key == K_LEFT or event.key == K_a:
                        self.move_left = False
                    if event.key == K_RIGHT or event.key == K_d:
                        self.move_right = False
                    if event.key == K_UP or event.key == K_w:
                        self.move_up = False
                    if event.key == K_DOWN or event.key == K_s:
                        self.move_down = False
                    if event.key == K_x:
                        self.player.top = random.randint(0, WINDOWHEIGHT - self.player.height)
                        self.player.left = random.randint(0, WINDOWWIDTH - self.player.width)
                    if event.key == K_m:
                        if self.music_playing:
                            pygame.mixer.music.stop()
                        else:
                            pygame.mixer.music.play(-1, 0.0)
                        self.music_playing = not self.music_playing

                    if event.type == MOUSEBUTTONUP:
                        self.foods.append(pygame.Rect(event.pos[0] - 10, event.pos[1] - 10, 20, 20))
                        self.food_counter += 1
                        if self.food_counter >= NEWFOOD:
                            self.food_counter = 0
                            self.foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - 20), random.randint(0, WINDOWHEIGHT - 20), 20, 20))

            # Move the player.
            if self.move_down and self.player.bottom < WINDOWHEIGHT:
                self.player.top += MOVESPEED
            if self.move_up and self.player.top > 0:
                self.player.top -= MOVESPEED
            if self.move_left and self.player.left > 0:
                self.player.left -= MOVESPEED
            if self.move_right and self.player.right < WINDOWWIDTH:
                self.player.right += MOVESPEED

            # Check whether the block has intersected with any food squares.
            for food in self.foods[:]:
                if self.player.colliderect(food):
                    self.foods.remove(food)
                    self.player = pygame.Rect(self.player.left, self.player.top, self.player.width + 2, self.player.height + 2)
                    self.player_stretched_image = pygame.transform.scale(self.player_image, (self.player.width, self.player.height))
                    self.pickup_sound.play()
            
            # Draw the white background onto the surface.
            self.window_surface.fill(WHITE)
            
            # Draw the food.
            for food in self.foods:
                self.window_surface.blit(self.food_image, food)

            # Draw the block onto the surface.
            self.window_surface.blit(self.player_stretched_image, self.player)

            # Draw the window onto the screen.
            pygame.display.update()
            self.main_clock.tick(40)


def main():
    pygame.init()
    game = Game()
    game.run()
    pygame.quit()
    

if __name__ == "__main__":
    main()
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@ThomasL: die `run_loop`-Variable brauchst Du nicht, weil Du die run-Methode einfach per `return` verlassen kannst.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Yepp, ist ein Überbleibsel einer früheren Lösung ohne die Klasse, kann definitiv weg. :-)

Es ging mir hauptsächlich darum, die beschriebenen Audioprobleme nachzuvollziehen zu können.
Ich stimme __deets__ zu, das da was mit der Installation von Python und/oder Pygame nicht ganz stimmt.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
grtur
User
Beiträge: 3
Registriert: Donnerstag 14. April 2022, 03:54
Wohnort: Münster/Westfalen

Hi.
Zuerst mal meinen aller herzlichsten Dank an ThomasL. für die viele Mühe, die Du dir gemacht hast. Da aber leider auch Deine Variante an der gleichen Stelle abgestürzt ist, habe ich heute meinen Rechner wieder "jungfräulich" gemacht, da es wohl tatsächlich an der Installation lag. Ich vermute, dass bei Upgrade von Windows 10 auf Windows 11 meine Pythoninstallation gekillt worden ist. Also hab ich heute zuerst Windows 11 neu installiert und dann erst Python und zuletzt Pygame neu installiert. Jetzt läuft das Programm so, wie es soll - sogar mit MIDI und auch mit mp3 .
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Das freut mich für dich, dann kannst du jetzt weitermachen und dein kleines Projekt vervollständigen. Viel Erfolg und Spaß dabei.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Antworten