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
  9WINDOW_WIDTH = 1280
 10WINDOW_HEIGHT = 720
 11WINDOW_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 GameView(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__(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_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(
 63            ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
 64        )
 65
 66        self.player_sprite = arcade.Sprite(self.player_texture)
 67        self.player_sprite.center_x = 64
 68        self.player_sprite.center_y = 128
 69
 70        self.player_list = arcade.SpriteList()
 71        self.player_list.append(self.player_sprite)
 72
 73        self.wall_list = arcade.SpriteList(use_spatial_hash=True)
 74        self.coin_list = arcade.SpriteList(use_spatial_hash=True)
 75
 76        # Create the ground
 77        # This shows using a loop to place multiple sprites horizontally
 78        for x in range(0, 1250, 64):
 79            wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
 80            wall.center_x = x
 81            wall.center_y = 32
 82            self.wall_list.append(wall)
 83
 84        # Put some crates on the ground
 85        # This shows using a coordinate list to place sprites
 86        coordinate_list = [[512, 96], [256, 96], [768, 96]]
 87
 88        for coordinate in coordinate_list:
 89            # Add a crate on the ground
 90            wall = arcade.Sprite(
 91                ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
 92            )
 93            wall.position = coordinate
 94            self.wall_list.append(wall)
 95
 96        # Add coins to the world
 97        for x in range(128, 1250, 256):
 98            coin = arcade.Sprite(":resources:images/items/coinGold.png", scale=COIN_SCALING)
 99            coin.center_x = x
100            coin.center_y = 96
101            self.coin_list.append(coin)
102
103        # Create a Platformer Physics Engine, this will handle moving our
104        # player as well as collisions between the player sprite and
105        # whatever SpriteList we specify for the walls.
106        # It is important to supply static to the walls parameter. There is a
107        # platforms parameter that is intended for moving platforms.
108        # If a platform is supposed to move, and is added to the walls list,
109        # it will not be moved.
110        self.physics_engine = arcade.PhysicsEnginePlatformer(
111            self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
112        )
113
114        # Initialize our camera, setting a viewport the size of our window.
115        self.camera = arcade.camera.Camera2D()
116
117        self.background_color = arcade.csscolor.CORNFLOWER_BLUE
118
119    def on_draw(self):
120        """Render the screen."""
121
122        # Clear the screen to the background color
123        self.clear()
124
125        # Activate our camera before drawing
126        self.camera.use()
127
128        # Draw our sprites
129        self.player_list.draw()
130        self.wall_list.draw()
131        self.coin_list.draw()
132
133    def on_update(self, delta_time):
134        """Movement and Game Logic"""
135
136        # Move the player using our physics engine
137        self.physics_engine.update()
138
139        # See if we hit any coins
140        coin_hit_list = arcade.check_for_collision_with_list(
141            self.player_sprite, self.coin_list
142        )
143
144        # Loop through each coin we hit (if any) and remove it
145        for coin in coin_hit_list:
146            # Remove the coin
147            coin.remove_from_sprite_lists()
148            arcade.play_sound(self.collect_coin_sound)
149
150        # Center our camera on the player
151        self.camera.position = self.player_sprite.position
152
153    def on_key_press(self, key, modifiers):
154        """Called whenever a key is pressed."""
155
156        if key == arcade.key.ESCAPE:
157            self.setup()
158
159        if key == arcade.key.UP or key == arcade.key.W:
160            if self.physics_engine.can_jump():
161                self.player_sprite.change_y = PLAYER_JUMP_SPEED
162                arcade.play_sound(self.jump_sound)
163
164        if key == arcade.key.LEFT or key == arcade.key.A:
165            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
166        elif key == arcade.key.RIGHT or key == arcade.key.D:
167            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
168
169    def on_key_release(self, key, modifiers):
170        """Called whenever a key is released."""
171
172        if key == arcade.key.LEFT or key == arcade.key.A:
173            self.player_sprite.change_x = 0
174        elif key == arcade.key.RIGHT or key == arcade.key.D:
175            self.player_sprite.change_x = 0
176
177
178def main():
179    """Main function"""
180    window = GameView()
181    window.setup()
182    arcade.run()
183
184
185if __name__ == "__main__":
186    main()

Run This Chapter

python -m arcade.examples.platform_tutorial.09_sound