Pygame Game Development

Add Sound to the Game

Our game, so far, has visual effects only.

Let’s add sound effects to the game. The program will play a sound each time the bat hits the ball.

Pygame provides a module called pygame.mixer to load and playback the music.

pygame.mixer.Sound() function:

This function creates a new Sound object from a file. The sound object pygame.mixer.Sound is created by calling the pygame.mixer.Sound() function. Within the parenthesis, there is one parameter of string data type that specifies the sound file name that you want to play. Pygame supports .wav, .mp3, or .ogg file formats.

The following are the statements to play the songs.

To load the song.

>>> pygame.mixer.music.load(‘filename.wav’)

The Sound object has play() method. To play the song once, call the play() method as below:

>>> pygame.mixer.music.play(0)

To plat the song for ever:

>>> pygame.mixer.music.play(-1)

Let us now modify the game program to add sound.  The program will music every time the bat hits the ball.

Program Name: pygame_hitBall_Score_Time_Sound.py

Image file: ball.png

Sound file: MusicBox.wav

PROBRAM EXAMPLE: HIT BALL WITH BAT KEEPING SCORE, TIME, AND PLAY MUSIC
# This program moves the ball randomly.
# The bat is moved by the keyboard arrow keys.
# The player moves the bat to hit the ball.
import pygame
import time
import random
# Initialize pygame module 
pygame.init()
pygame.mixer.init() # Initialize mixer
######      SET UP      ######
# Set screen width and height.
screen_width = 800
screen_height = 600
# Define colors tuples RGB values.
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
MAGENTA = (255, 0, 255)
# Create a display surface width = 800 pixels, height = 600 pixels.
screen = pygame.display.set_mode((screen_width, screen_height))
# Give our display window a name 'HitBall_Score_Time_Sound'.
pygame.display.set_caption('HitBall_Score_Time_Sound')
# time.clock() function provides the clock for app.
clock = pygame.time.Clock()

###### Ball Image load
img = pygame.image.load('ball.png')
####### Load sound file. 
pygame.mixer.music.load("MusicBox.wav")	  # 1
#######
bat_width = 30     # Set bat width and bat height.
bat_height = 50
bat_move = 20  # Set bat movement in pixels each key press.
ball_width = 100

###### Define text font to display text on hitting the ball.
font = pygame.font.SysFont("arial black", 48)
text = font.render("I hit the ball", True, BLUE)
textRect = text.get_rect()
textRect.center = screen_width//2, screen_height * 0.2
######

# Define font for "bat_out_of_screen" message asking player to Continue or Quit.
fontCorQ = pygame.font.SysFont(None, 30)
######      FUNCTIONS      ######
###### Function to ask player to Continue or Quit.
def userInput(cont_quit, color):
    contOrQuit = fontCorQ.render(cont_quit, True, color)
    screen.blit(contOrQuit, [screen_width/5, 4*screen_height/5])
######

###### Define function for text font for number of hits.
def score(count):
    fontS = pygame.font.SysFont('arial black', 24) # Score Text font and size.
    textS = fontS.render('Strikes ='+str(count), True, MAGENTA) #Score text color.
    screen.blit(textS, (20, 0)) # Position of  score count text.
    pygame.display.update()
######

###### Define function for time remaining. Select text for printing time.
def time1(seconds):
    fontT = pygame.font.SysFont('arial black', 36) # Font size=36
    textT = fontT.render('Time remaining ='+str(int(seconds/bat_move)),True, BLACK)
    screen.blit(textT, (300, 0)) # Text position = (300, 0) tuple.
    pygame.display.update()
######
######       Main loop      ######
def mainLoop():
    running = True
    bat_out_of_screen = False
###### Initialize hit count and number of seconds remaining in the game.
    count = 0
    seconds = 120 * bat_move
    
###### Initialize bat position.
    xBat = screen_width / 2
    yBat = screen_height / 2
###### Initialize the number of pixels the bat moves at each key press.  
    batXstep = 0  
    batYstep = 0 
###### Ball initial position coordinates.
    x = screen_width / 2
    y = screen_height * 0.7
######
    while running:
###### Ask player to play again or quit.
        while bat_out_of_screen == True:
            screen.fill(WHITE)
            userInput("Bat is out of window! Press Q to Quit or C to Continue", RED)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        running = False
                        bat_out_of_screen = False
                    if event.key == pygame.K_c:
                        mainLoop()
###### Keyboard Events for bat movement.
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    batXstep = -bat_move
                    batYstep = 0
                elif event.key == pygame.K_RIGHT:
                    batXstep = bat_move
                    batYstep = 0
                elif event.key == pygame.K_UP:
                    batYstep = -bat_move
                    batXstep = 0
                elif event.key == pygame.K_DOWN:
                    batYstep = bat_move
                    batXstep = 0
            if event.type == pygame.KEYUP:
                    batYstep = 0 # if the key is up, do not change bat position.
                    batXstep = 0

###### Check if bat is out of display window.
        if xBat >= screen_width - 50 or xBat < 50 or yBat >= screen_height - 50 or yBat < 50:
            bat_out_of_screen = True
 
        xBat += batXstep
        yBat += batYstep
######
        screen.fill(WHITE)
###### Draw bat rectangle and update the screen.
        pygame.draw.rect(screen, GREEN, [xBat, yBat, bat_width, bat_height])
        pygame.display.update()

###### Generate new ball location randomly for each new frame.  
        x = x + random.randint(-30, 30) 
        y = y + random.randint(-30, 30)
        
###### Check if ball reaches the screen window.
###### Back-off the ball back by 50 pixels if the ball reaches screen boundary.
        back_off = 50
        if  x > 700:
            x = x - back_off
        elif x < 0:
            x = back_off
        if y > 500:
            y = y - back_off
        elif y < 0:
            y = back_off
            
# The blit function draws the ball image on the screen object at location (x, y).
        screen.blit(img, (x, y))
        pygame.display.update()
###### Call score function.
        score(count)
        time1(seconds)
######
# If bat comes within 30 pixels of ball’s left x-coordinate
# AND the bat comes within ball’s left edge coordinate + ball_width, then
# test if the bat comes within 30 pixels of ball’s top y-coordinate
# AND the ball’s top edge y-coordinate +ball_width.
        if xBat > x - 30 and xBat < x + ball_width:
            if yBat > y - 30 and yBat < y + ball_width:
                count += 1
                screen.blit(text, textRect) 
# If Bat hit the ball, then print text "I hit the ball."
                pygame.display.update()
                pygame.mixer.music.play() 
# Call the play() method.		# 2
        seconds -= 1
        if seconds == 0:
            running = False
        clock.tick(60)
        pygame.time.delay(50)

    pygame.quit()
    quit()
 
mainLoop()

Detailed Line-by-line Explanation of the Program:

There are only two changes to the previous program to play sounds.

1) To load the song, we use the function pygame.mixer.music.load(‘filename.wav’)

###### Load sound file. 
pygame.mixer.music.load("MusicBox.wav")	  # 1)
######

2) If there is a collision between the bat and the ball (we find this by checking if the bat is within 30 pixels of the ball), we call the method pygame.mixer.music.play().

# If bat comes within 30 pixels of ball’s left x-coordinate
# AND the bat comes within ball’s left edge coordinate + ball_width, then
# test if the bat comes within 30 pixels of ball’s top y-coordinate
# AND the ball’s top edge y-coordinate +ball_width.
        if xBat > x - 30 and xBat < x + ball_width:
            if yBat > y - 30 and yBat < y +ball_width:
                count += 1
                screen.blit(text, textRect) # If Bat hit the ball
                pygame.display.update()  # print text "I hit the ball".
                pygame.mixer.music.play() 
# Call the play() method.	# 2)
        seconds -= 1
        if seconds == 0:
            running = False

Copyright © 2019 – 2021 softwareprogramming4kids.com

All Rights Reserved

Verified by MonsterInsights