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
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