Step 6 - Add Coins And Sound

../../_images/listing_06.png

The code below adds coins that we can collect. It also adds a sound to be played when the user hits a coin, or presses the jump button.

We check to see if the user hits a coin by the arcade.check_for_collision_with_list function. Just pass the player sprite, along with a SpriteList that holds the coins. The function returns a list of coins in contact with the player sprite. If no coins are in contact, the list is empty.

The method Sprite.remove_from_sprite_lists will remove that sprite from all lists, and effectively the game.

Notice that any transparent “white-space” around the image counts as the hitbox. You can trim the space in a graphics editor, or in the second section, we’ll show you how to specify the hitbox.

Add Coins and Sound
  1"""
  2Platformer Game
  3"""
  4import arcade
  5
  6# Constants
  7SCREEN_WIDTH = 1000
  8SCREEN_HEIGHT = 650
  9SCREEN_TITLE = "Platformer"
 10
 11# Constants used to scale our sprites from their original size
 12CHARACTER_SCALING = 1
 13TILE_SCALING = 0.5
 14COIN_SCALING = 0.5
 15
 16# Movement speed of player, in pixels per frame
 17PLAYER_MOVEMENT_SPEED = 5
 18GRAVITY = 1
 19PLAYER_JUMP_SPEED = 20
 20
 21# How many pixels to keep as a minimum margin between the character
 22# and the edge of the screen.
 23LEFT_VIEWPORT_MARGIN = 250
 24RIGHT_VIEWPORT_MARGIN = 250
 25BOTTOM_VIEWPORT_MARGIN = 50
 26TOP_VIEWPORT_MARGIN = 100
 27
 28
 29class MyGame(arcade.Window):
 30    """
 31    Main application class.
 32    """
 33
 34    def __init__(self):
 35
 36        # Call the parent class and set up the window
 37        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 38
 39        # These are 'lists' that keep track of our sprites. Each sprite should
 40        # go into a list.
 41        self.coin_list = None
 42        self.wall_list = None
 43        self.player_list = None
 44
 45        # Separate variable that holds the player sprite
 46        self.player_sprite = None
 47
 48        # Our physics engine
 49        self.physics_engine = None
 50
 51        # Used to keep track of our scrolling
 52        self.view_bottom = 0
 53        self.view_left = 0
 54
 55        # Load sounds
 56        self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
 57        self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
 58
 59        arcade.set_background_color(arcade.csscolor.CORNFLOWER_BLUE)
 60
 61    def setup(self):
 62        """ Set up the game here. Call this function to restart the game. """
 63
 64        # Used to keep track of our scrolling
 65        self.view_bottom = 0
 66        self.view_left = 0
 67
 68        # Create the Sprite lists
 69        self.player_list = arcade.SpriteList()
 70        self.wall_list = arcade.SpriteList()
 71        self.coin_list = arcade.SpriteList()
 72
 73        # Set up the player, specifically placing it at these coordinates.
 74        image_source = ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
 75        self.player_sprite = arcade.Sprite(image_source, CHARACTER_SCALING)
 76        self.player_sprite.center_x = 64
 77        self.player_sprite.center_y = 128
 78        self.player_list.append(self.player_sprite)
 79
 80        # Create the ground
 81        # This shows using a loop to place multiple sprites horizontally
 82        for x in range(0, 1250, 64):
 83            wall = arcade.Sprite(":resources:images/tiles/grassMid.png", TILE_SCALING)
 84            wall.center_x = x
 85            wall.center_y = 32
 86            self.wall_list.append(wall)
 87
 88        # Put some crates on the ground
 89        # This shows using a coordinate list to place sprites
 90        coordinate_list = [[512, 96],
 91                           [256, 96],
 92                           [768, 96]]
 93
 94        for coordinate in coordinate_list:
 95            # Add a crate on the ground
 96            wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", TILE_SCALING)
 97            wall.position = coordinate
 98            self.wall_list.append(wall)
 99
100        # Use a loop to place some coins for our character to pick up
101        for x in range(128, 1250, 256):
102            coin = arcade.Sprite(":resources:images/items/coinGold.png", COIN_SCALING)
103            coin.center_x = x
104            coin.center_y = 96
105            self.coin_list.append(coin)
106
107        # Create the 'physics engine'
108        self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite,
109                                                             self.wall_list,
110                                                             GRAVITY)
111
112    def on_draw(self):
113        """ Render the screen. """
114
115        # Clear the screen to the background color
116        arcade.start_render()
117
118        # Draw our sprites
119        self.wall_list.draw()
120        self.coin_list.draw()
121        self.player_list.draw()
122
123    def on_key_press(self, key, modifiers):
124        """Called whenever a key is pressed. """
125
126        if key == arcade.key.UP or key == arcade.key.W:
127            if self.physics_engine.can_jump():
128                self.player_sprite.change_y = PLAYER_JUMP_SPEED
129                arcade.play_sound(self.jump_sound)
130        elif key == arcade.key.LEFT or key == arcade.key.A:
131            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
132        elif key == arcade.key.RIGHT or key == arcade.key.D:
133            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
134
135    def on_key_release(self, key, modifiers):
136        """Called when the user releases a key. """
137
138        if key == arcade.key.LEFT or key == arcade.key.A:
139            self.player_sprite.change_x = 0
140        elif key == arcade.key.RIGHT or key == arcade.key.D:
141            self.player_sprite.change_x = 0
142
143    def update(self, delta_time):
144        """ Movement and game logic """
145
146        # Move the player with the physics engine
147        self.physics_engine.update()
148
149        # See if we hit any coins
150        coin_hit_list = arcade.check_for_collision_with_list(self.player_sprite,
151                                                             self.coin_list)
152
153        # Loop through each coin we hit (if any) and remove it
154        for coin in coin_hit_list:
155            # Remove the coin
156            coin.remove_from_sprite_lists()
157            # Play a sound
158            arcade.play_sound(self.collect_coin_sound)
159
160        # --- Manage Scrolling ---
161
162        # Track if we need to change the viewport
163
164        changed = False
165
166        # Scroll left
167        left_boundary = self.view_left + LEFT_VIEWPORT_MARGIN
168        if self.player_sprite.left < left_boundary:
169            self.view_left -= left_boundary - self.player_sprite.left
170            changed = True
171
172        # Scroll right
173        right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_VIEWPORT_MARGIN
174        if self.player_sprite.right > right_boundary:
175            self.view_left += self.player_sprite.right - right_boundary
176            changed = True
177
178        # Scroll up
179        top_boundary = self.view_bottom + SCREEN_HEIGHT - TOP_VIEWPORT_MARGIN
180        if self.player_sprite.top > top_boundary:
181            self.view_bottom += self.player_sprite.top - top_boundary
182            changed = True
183
184        # Scroll down
185        bottom_boundary = self.view_bottom + BOTTOM_VIEWPORT_MARGIN
186        if self.player_sprite.bottom < bottom_boundary:
187            self.view_bottom -= bottom_boundary - self.player_sprite.bottom
188            changed = True
189
190        if changed:
191            # Only scroll to integers. Otherwise we end up with pixels that
192            # don't line up on the screen
193            self.view_bottom = int(self.view_bottom)
194            self.view_left = int(self.view_left)
195
196            # Do the scrolling
197            arcade.set_viewport(self.view_left,
198                                SCREEN_WIDTH + self.view_left,
199                                self.view_bottom,
200                                SCREEN_HEIGHT + self.view_bottom)
201
202
203def main():
204    """ Main method """
205    window = MyGame()
206    window.setup()
207    arcade.run()
208
209
210if __name__ == "__main__":
211    main()

Note

Spend time placing the coins where you would like them. If you have extra time, try adding more than just coins. Also add gems or keys from the graphics provided.

You could also subclass the coin sprite and add an attribute for a score value. Then you could have coins worth one point, and gems worth 5, 10, and 15 points.