Step 9 - Adding Sound#

Our game has a lot of graphics so far, but doesn’t have any sound yet. Let’s change that! In this chapter we will add a sound when the player collects the coins, as well as when they jump.

Loading and playing sounds in Arcade is very easy. We will only need two functions for this:

In our __init__ function, we will add these two lines to load our coin collection and jump sounds.

self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")

Note

Why are we not adding empty variables to __init__ and initializing them in setup like our other objects?

This is because sounds are a static asset within our game. If we reset the game, the sounds don’t change, so it’s not worth re-loading them.

Now we can play these sounds by simple adding the play_sound function wherever we want them to occur. Let’s add one alongside our removal of coins in the on_update function.

# Within on_update
for coin in coin_hit_list:
    coin.remove_from_sprite_lists()
    arcade.play_sound(self.collect_coin_sound)

This will play a sound whenever we collect a coin. We can add a jump sound by adding this to our UP block for jumping in the on_key_press function:

# Within on_key_press
if key == arcade.key.UP or key == arcade.key.W:
    if self.physics_engine.can_jump():
        self.player_sprite.change_y = PLAYER_JUMP_SPEED
        arcade.play_sound(self.jump_sound)

Now we will also have a sound whenever we jump.

Documentation for arcade.Sound

Source Code#

Load the Map#
  1"""
  2Platformer Game
  3
  4python -m arcade.examples.platform_tutorial.09_sound
  5"""
  6import arcade
  7
  8# Constants
  9SCREEN_WIDTH = 800
 10SCREEN_HEIGHT = 600
 11SCREEN_TITLE = "Platformer"
 12
 13# Constants used to scale our sprites from their original size
 14TILE_SCALING = 0.5
 15COIN_SCALING = 0.5
 16
 17# Movement speed of player, in pixels per frame
 18PLAYER_MOVEMENT_SPEED = 5
 19GRAVITY = 1
 20PLAYER_JUMP_SPEED = 20
 21
 22
 23class MyGame(arcade.Window):
 24    """
 25    Main application class.
 26    """
 27
 28    def __init__(self):
 29
 30        # Call the parent class and set up the window
 31        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 32
 33        # Variable to hold our texture for our player
 34        self.player_texture = None
 35
 36        # Separate variable that holds the player sprite
 37        self.player_sprite = None
 38
 39        # SpriteList for our player
 40        self.player_list = None
 41
 42        # SpriteList for our boxes and ground
 43        # Putting our ground and box Sprites in the same SpriteList
 44        # will make it easier to perform collision detection against
 45        # them later on. Setting the spatial hash to True will make
 46        # collision detection much faster if the objects in this
 47        # SpriteList do not move.
 48        self.wall_list = None
 49
 50        # SpriteList for coins the player can collect
 51        self.coin_list = None
 52
 53        # A variable to store our camera object
 54        self.camera = None
 55
 56        # Load sounds
 57        self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
 58        self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
 59
 60    def setup(self):
 61        """Set up the game here. Call this function to restart the game."""
 62        self.player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
 63
 64        self.player_sprite = arcade.Sprite(self.player_texture)
 65        self.player_sprite.center_x = 64
 66        self.player_sprite.center_y = 128
 67
 68        self.player_list = arcade.SpriteList()
 69        self.player_list.append(self.player_sprite)
 70
 71        self.wall_list = arcade.SpriteList(use_spatial_hash=True)
 72        self.coin_list = arcade.SpriteList(use_spatial_hash=True)
 73
 74        # Create the ground
 75        # This shows using a loop to place multiple sprites horizontally
 76        for x in range(0, 1250, 64):
 77            wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
 78            wall.center_x = x
 79            wall.center_y = 32
 80            self.wall_list.append(wall)
 81
 82        # Put some crates on the ground
 83        # This shows using a coordinate list to place sprites
 84        coordinate_list = [[512, 96], [256, 96], [768, 96]]
 85
 86        for coordinate in coordinate_list:
 87            # Add a crate on the ground
 88            wall = arcade.Sprite(
 89                ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
 90            )
 91            wall.position = coordinate
 92            self.wall_list.append(wall)
 93
 94        # Add coins to the world
 95        for x in range(128, 1250, 256):
 96            coin = arcade.Sprite(":resources:images/items/coinGold.png", scale=COIN_SCALING)
 97            coin.center_x = x
 98            coin.center_y = 96
 99            self.coin_list.append(coin)
100
101        # Create a Platformer Physics Engine, this will handle moving our
102        # player as well as collisions between the player sprite and
103        # whatever SpriteList we specify for the walls.
104        # It is important to supply static to the walls parameter. There is a
105        # platforms parameter that is intended for moving platforms.
106        # If a platform is supposed to move, and is added to the walls list,
107        # it will not be moved.
108        self.physics_engine = arcade.PhysicsEnginePlatformer(
109            self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
110        )
111
112        # Initialize our camera, setting a viewport the size of our window.
113        self.camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))
114
115        self.background_color = arcade.csscolor.CORNFLOWER_BLUE
116
117    def on_draw(self):
118        """Render the screen."""
119
120        # Clear the screen to the background color
121        self.clear()
122
123        # Activate our camera before drawing
124        self.camera.use()
125
126        # Draw our sprites
127        self.player_list.draw()
128        self.wall_list.draw()
129        self.coin_list.draw()
130
131    def on_update(self, delta_time):
132        """Movement and Game Logic"""
133
134        # Move the player using our physics engine
135        self.physics_engine.update()
136
137        # See if we hit any coins
138        coin_hit_list = arcade.check_for_collision_with_list(
139            self.player_sprite, self.coin_list
140        )
141
142        # Loop through each coin we hit (if any) and remove it
143        for coin in coin_hit_list:
144            # Remove the coin
145            coin.remove_from_sprite_lists()
146            arcade.play_sound(self.collect_coin_sound)
147
148        # Center our camera on the player
149        self.camera.center(self.player_sprite.position)
150
151    def on_key_press(self, key, modifiers):
152        """Called whenever a key is pressed."""
153
154        if key == arcade.key.ESCAPE:
155            self.setup()
156
157        if key == arcade.key.UP or key == arcade.key.W:
158            if self.physics_engine.can_jump():
159                self.player_sprite.change_y = PLAYER_JUMP_SPEED
160                arcade.play_sound(self.jump_sound)
161
162        if key == arcade.key.LEFT or key == arcade.key.A:
163            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
164        elif key == arcade.key.RIGHT or key == arcade.key.D:
165            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
166
167    def on_key_release(self, key, modifiers):
168        """Called whenever a key is released."""
169
170        if key == arcade.key.LEFT or key == arcade.key.A:
171            self.player_sprite.change_x = 0
172        elif key == arcade.key.RIGHT or key == arcade.key.D:
173            self.player_sprite.change_x = 0
174
175
176def main():
177    """Main function"""
178    window = MyGame()
179    window.setup()
180    arcade.run()
181
182
183if __name__ == "__main__":
184    main()

Run This Chapter#

python -m arcade.examples.platform_tutorial.09_sound