Sounds and Music with PyGame



Video games are meant to immerse the player into a sort of virtual reality. We do this mainly visually, but it can make a massive difference and be a massive improvement to your game if you add sounds as well.

Sounds generally come in two major forms: Either "ambient" noise or as results of player actions. With PyGame, you get two choices: Music or Sounds. Music will just play in the background when you call it to, and sounds will play at any time you call them to play. We're going to cover both here by adding them both to our current game. First, we will use a simple tune from YouTube as our game's music and then we'll add a "crash" sound that we will play if we hit any of the blocks.

To start, let's make a sound:

crash_sound = pygame.mixer.Sound("crash.wav")

The above will assign the crash.wav sound file to play when we call crash_sound within PyGame's sound playing functionality. Notice the file is .wav. PyGame can handle .mp3 as well, but it is somewhat glitchy, and will work sometimes and other times it wont. For the safest bet, go with .wav.

Now that we know how to call sounds, how can we do music?

pygame.mixer.music.load('jazz.wav')
pygame.mixer.music.play(-1)

The above code will play the music file indefinitely (though you can call it to stop). The -1 signals PyGame to just play forever, but, if you put, say, a 5 in there, then the music would play once and 5 more times.

Now, we want the music to play, and it is, then we need the crash sound to play when crashed. Also, we'd like to stop the music if this is the case.

So, within our crash function...

def crash():
    ####################################
    pygame.mixer.Sound.play(crash_sound)
    pygame.mixer.music.stop()
    ####################################
    largeText = pygame.font.SysFont("comicsansms",115)
    TextSurf, TextRect = text_objects("You Crashed", largeText)

Above, we're calling PyGame to play the crash_sound, as well as to stop the music. This means the music will start over again if the game is re-played.

Now, the only other thing we may want to do is learn how to pause/unpause music when the player pauses the game. This is easy enough.

In our paused function:

def paused():
    ############
    pygame.mixer.music.pause()
    #############

And then of course we must unpause it:

def unpause():
    global pause
    #################
    pygame.mixer.music.unpause()
    #################
    pause = False

Full PyGame code:

import pygame
import time
import random
 
pygame.init()

#############
crash_sound = pygame.mixer.Sound("crash.wav")
#############
 
display_width = 800
display_height = 600
 
black = (0,0,0)
white = (255,255,255)

red = (200,0,0)
green = (0,200,0)

bright_red = (255,0,0)
bright_green = (0,255,0)
 
block_color = (53,115,255)
 
car_width = 73
 
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()
 
carImg = pygame.image.load('racecar.png')
gameIcon = pygame.image.load('carIcon.png')

pygame.display.set_icon(gameIcon)

pause = False
#crash = True
 
def things_dodged(count):
    font = pygame.font.SysFont("comicsansms", 25)
    text = font.render("Dodged: "+str(count), True, black)
    gameDisplay.blit(text,(0,0))
 
def things(thingx, thingy, thingw, thingh, color):
    pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
 
def car(x,y):
    gameDisplay.blit(carImg,(x,y))
 
def text_objects(text, font):
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()
 
 
def crash():
    ####################################
    pygame.mixer.Sound.play(crash_sound)
    pygame.mixer.music.stop()
    ####################################
    largeText = pygame.font.SysFont("comicsansms",115)
    TextSurf, TextRect = text_objects("You Crashed", largeText)
    TextRect.center = ((display_width/2),(display_height/2))
    gameDisplay.blit(TextSurf, TextRect)
    

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                
        

        button("Play Again",150,450,100,50,green,bright_green,game_loop)
        button("Quit",550,450,100,50,red,bright_red,quitgame)

        pygame.display.update()
        clock.tick(15) 

def button(msg,x,y,w,h,ic,ac,action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(gameDisplay, ac,(x,y,w,h))
        if click[0] == 1 and action != None:
            action()         
    else:
        pygame.draw.rect(gameDisplay, ic,(x,y,w,h))
    smallText = pygame.font.SysFont("comicsansms",20)
    textSurf, textRect = text_objects(msg, smallText)
    textRect.center = ( (x+(w/2)), (y+(h/2)) )
    gameDisplay.blit(textSurf, textRect)
    

def quitgame():
    pygame.quit()
    quit()

def unpause():
    global pause
    pygame.mixer.music.unpause()
    pause = False
    

def paused():
    ############
    pygame.mixer.music.pause()
    #############
    largeText = pygame.font.SysFont("comicsansms",115)
    TextSurf, TextRect = text_objects("Paused", largeText)
    TextRect.center = ((display_width/2),(display_height/2))
    gameDisplay.blit(TextSurf, TextRect)
    

    while pause:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()


        button("Continue",150,450,100,50,green,bright_green,unpause)
        button("Quit",550,450,100,50,red,bright_red,quitgame)

        pygame.display.update()
        clock.tick(15)   


def game_intro():

    intro = True

    while intro:
        for event in pygame.event.get():
            #print(event)
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                
        gameDisplay.fill(white)
        largeText = pygame.font.SysFont("comicsansms",115)
        TextSurf, TextRect = text_objects("A bit Racey", largeText)
        TextRect.center = ((display_width/2),(display_height/2))
        gameDisplay.blit(TextSurf, TextRect)

        button("GO!",150,450,100,50,green,bright_green,game_loop)
        button("Quit",550,450,100,50,red,bright_red,quitgame)

        pygame.display.update()
        clock.tick(15)
        
        
    
    

    
def game_loop():
    global pause
    ############
    pygame.mixer.music.load('jazz.wav')
    pygame.mixer.music.play(-1)
    ############
    x = (display_width * 0.45)
    y = (display_height * 0.8)
 
    x_change = 0
 
    thing_startx = random.randrange(0, display_width)
    thing_starty = -600
    thing_speed = 4
    thing_width = 100
    thing_height = 100
 
    thingCount = 1
 
    dodged = 0
 
    gameExit = False
 
    while not gameExit:
 
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
 
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_change = -5
                if event.key == pygame.K_RIGHT:
                    x_change = 5
                if event.key == pygame.K_p:
                    pause = True
                    paused()
                    
 
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    x_change = 0
 
        x += x_change
        gameDisplay.fill(white)
 
        things(thing_startx, thing_starty, thing_width, thing_height, block_color)
 
 
        
        thing_starty += thing_speed
        car(x,y)
        things_dodged(dodged)
 
        if x > display_width - car_width or x < 0:
            crash()
 
        if thing_starty > display_height:
            thing_starty = 0 - thing_height
            thing_startx = random.randrange(0,display_width)
            dodged += 1
            thing_speed += 1
            thing_width += (dodged * 1.2)
 
        if y < thing_starty+thing_height:
            print('y crossover')
 
            if x > thing_startx and x < thing_startx + thing_width or x+car_width > thing_startx and x + car_width < thing_startx+thing_width:
                print('x crossover')
                crash()
        
        pygame.display.update()
        clock.tick(60)

game_intro()
game_loop()
pygame.quit()
quit()

There exists 1 challenge(s) for this tutorial. for access to these, video downloads, and no ads.


There exists 2 quiz/question(s) for this tutorial. for access to these, video downloads, and no ads.

That is all for the PyGame basics series. You can choose another topic from the


Alternatively, you can check out the PyOpenGL series, which uses OpenGL to create 3D renderings using PyGame:





  • Introduction to PyGame
  • Displaying images with PyGame
  • Moving an image around in PyGame
  • Adding boundaries
  • Displaying text to PyGame screen
  • Drawing objects with PyGame
  • Crashing
  • PyGame Score
  • Drawing Objects and Shapes in PyGame
  • Creating a start menu
  • PyGame Buttons, part 1, drawing the rectangle
  • PyGame Buttons, part 2, making the buttons interactive
  • PyGame Buttons, part 3, adding text to the button
  • PyGame Buttons, part 4, creating a general PyGame button function
  • PyGame Buttons, part 5, running functions on a button click
  • Converting PyGame to an executable
  • Adding a pause function to our game and Game Over
  • PyGame Icon
  • Sounds and Music with PyGame