Sound in Python and Cockroach

Introduction

This is part eight of a multi-article series of articles showing how to create a 2D video game. In this part we add how to create Sound in Python and Cockroach for database operations such as saving and restoring game screens as well as player score. In this article part, we see how to add a song and sound effects for various occurances, including the following: when a brain is thrown, when a zombie is hit by the brain, and when the player collides with a zombie. In the articles following this one, we will learn to track player score, change game speed and difficulty, and even add reading mouse input. We will later add multiplayer capability.

Prerequisites

  • MOST IMPERATIVE: study part one through part seven where we learned to create and set up the GUI with Cockroach, create Sprites with PNG files and Sprite Lists, how to manage key strokes, how to move the Player in the GUI based on those key strokes, move zombies with some smarts, fire bullets using the space bar and move them, and detecting collisions between Sprites.

  • The full source code, images, and sound files are all available for download.

Python libraries for the game

Be sure to install the following libraries. PIP is an easy utility for this that is free to get and use.

1
2
3
4
5
6
7
8
import arcade # 2DGame-oriented Python framework.
import math # For a few math and movement-related calculations.
import random # For creating random numbers for block placement and enemy movement.
from datetime import datetime, timedelta # For making random number generation more random.
import os # For getting to the computer's file system to load sounds and images.
import sys # Needed to complement the os library above.
import psycopg2 # For data retrieval for the GUI using Cockroach.
import pyautogui # For finding out the resolution of the monitor to be sure our GUI is not too big.

In this article, before we play with adding sound, we’ll briefly review the function called check_for_collision_with_list(). The function does what it sounds like; checks for a collision between a Sprite and a designated Sprite List.

Syntax of check_for_collision_with_list

1
list_of_collisions = arcade.check_for_collision_with_list(single_sprite, list_sprites)

Now we will look at loading sounds into Python Arcade’s sound objects.

Load sounds with Arcade

The first thing to do is assign some Python Arcade sound-types with some MP3 files (provided in the full source zip file we listed at the top of this article), so these sound objects can be called later on when needed.

1
2
3
4
5
6
7
self.sound_song = arcade.load_sound("./resources/sounds/song-burpy.mp3")
self.sound_throw = arcade.load_sound("./resources/sounds/woosh.mp3")
self.sound_gasp_of_death = arcade.load_sound("./resources/sounds/gasp.mp3")
self.sound_bullet = arcade.load_sound("./resources/sounds/bullet.mp3")
self.sound_powerup = arcade.load_sound("./resources/sounds/powerup.mp3")
self.sound_munch = arcade.load_sound("./resources/sounds/munch.mp3")
self.sound_burp = arcade.load_sound("./resources/sounds/burp.mp3")

Now, when the game starts, we’ll set the background song playing. Python Arcade handles sound in a simplistic manner in the current Arcade version. It doesn’t allow for control of volume, a “play this sound in the background” parameter, repeat, pause, or stop. So we’ve made our background song long enough for most games but if you play past the end of the song, it will end and not restart. As far as layering sounds, the sound effects you play will not interrupt or otherwise disrupt the song playing in the background. Luckily, they blend seamlessly. The developers of Arcade are working on adding more sound parameters for an upcoming version of the library.

Background song using Arcade

Below is some of the script within our “start new game” function. See the full source file we linked to near the top of this article for all the code in this function. For the purpose of understanding the syntax and when/where to use sound commands, look to the bottom of this function where we instruct Python to begin the theme song we chose for this game.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def start_new_game(self):
    self.frame_count = 0
    self.game_over = False
    # Set up the Sprite lists.
    self.list_all_sprites = arcade.SpriteList()
    self.list_enemies = arcade.SpriteList()
    self.list_bullets = arcade.SpriteList()
    self.list_player_lives = arcade.SpriteList()
    self.list_blocks = arcade.SpriteList()
    # Initialize a title GUI sprite image to show game intro window.
    self.title = PlayerSprite("./resources/images/title.png", SCALE * 2.5)
    # Set up the monkey's Sprite.
    self.score = 0
    self.player_sprite = PlayerSprite("./resources/images/player.png", SCALE)
    self.list_all_sprites.append(self.player_sprite)
    self.lives = PLAYER_STARTING_LIVES
    # Play the song that will play in the background.
    arcade.play_sound(self.sound_song)
    # Play the powerup sound now so it is in memory for quick use later.
    arcade.play_sound(self.sound_powerup)

Now to finish taking the script for collision detection we wrote during the last session and adding in sound FX when there are collisions between different Sprites.

Sprite collision sound

As with all the articles in this series where we are building a 2D game, we cut code out of the script you see below that does not apply to sound-making. If you want to see ALL the code, download the zip file we provided a link to near the top of this article.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Go through all bullets (brains) currently in the GUI.
if not self.game_over:
    self.list_all_sprites.update()
    # Iterate through all bullets (brains)
    # currently on screen.
    for bullet in self.list_bullets:
        # Check for collision with all
        # enemies in the enemy sprite list.
        enemies = arcade.check_for_collision_with_list(bullet, self.list_enemies)
        # Cycle through all enemies hit by the current flying brain.
        i = -1
        for enemy in enemies:
            i += 1
            # Give the Player points for hitting an enemy,
            # influenced by difficulty level.
            self.score += int(100 * self.player_sprite.difficulty)
            # For enemy that was hit, set speed to zero.
            enemy.change_x = 0
            enemy.change_y = 0
            # Get the enemy image url into a temporary variable.
            url_image = enemy.url_image
            # Increase the enemy's size.
            new_scale = enemy.scale + 0.07
            # When the enemy gets to a certain
            # size, the enemy becomes "enraged".
            if new_scale > 0.59:
                new_scale = 0.6
                enemy.enraged = True
                # Is enraged sound enabled for THIS enemy?
                # This is where we utilize the "z" we added
                # before "char" in a previous article in this
                # series where we initialized the enemy Sprite
                # images. If we put the "z" in, then the "if"
                # below does not play the enraged sound.
                if url_image.find(enemy.guid) > -1:
                    # following builds this: "self.sound_char_02_enraged"
                    build_sound_name = enemy.which
                    arcade.play_sound(eval(build_sound_name))
                else:
                    arcade.play_sound(self.sound_powerup)
                # Change image for "enraged" version where in
                # this case the zombie now has red eyes.
                url_image = url_image.replace("front","enraged")
            else:
                # NOTE the power-up sound played here.
                arcade.play_sound(self.sound_powerup)

    # if player not invulnerable (respawning):
    if not self.player_sprite.respawning:
        # Check for collision between player and all enemies
        enemies = arcade.check_for_collision_with_list(self.player_sprite, self.list_enemies)
        #   If list of enemies hit created above has at least one enemy:
        if len(enemies) > 0:
            # NOTICE THE SOUNDS HERE.
            arcade.play_sound(self.sound_gasp_of_death)
            arcade.play_sound(self.sound_munch)
            arcade.play_sound(self.sound_burp)
            self.eaten = True
        else:
            self.eaten = False

Conclusion

In this part eight, we learned how to make Sound in Python and leveraged Cockroach to read and write data such as the GUI layout and keep score. We learned how to add a song and some sound effects for various things that happen during game play. In the articles following this one, we’ll learn to keep and modify score, display that score on the screen, and add tracking and changing of game speed. Code samples included.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.