Step 8 - Collecting Coins
Now that we can fully move around our game, we need to give the player an objective. A classic goal in video games is collecting coins, so let’s go ahead and add that.
In this chapter you will learn how to check for collisions with our player, and find out exactly what they collided with and do something with it. For now we will just remove the coin from the screen when they collect it, but in later chapters we will give the character a score, and add to it when they collect a coin. We will also start playing sounds later.
First off we will create a new SpriteList to hold our coins. Exactly like our other spritelist for
walls, go ahead and add a variable to the __init__
function to store it, and then initialize it
inside the setup
function. We will want to turn on spatial hashing for this list for now. If you
decided to have moving coins, you would want to turn that off.
# Inside __init__
self.coin_list = None
# Inside setup
self.coin_list = arcade.SpriteList(use_spatial_hash=True)
See if you can experiment with a way to add the coins to the SpriteList using what we’ve already learned.
The built-in resource for them is :resources:images/items/coinGold.png
. HINT: You’ll want to scale these
just like we did with our boxes and ground. If you get stuck, you can check the full source code below to
see how we’ve placed them following the same pattern we used for the ground.
Once you have placed the coins and added them to the coin_list
, don’t forget to add them to on_draw
.
self.coin_list.draw()
Now that we’re drawing our coins to the screen, how do we make them interact with the player? When the player
hits one, we want to remove it from the screen. To do this we will use arcade.check_for_collision_with_list()
function.
This function takes a single Sprite, in this instance our player, and a SpriteList, for us, the coins. It will return
a list containing all of the Sprites from the given SpriteList that the Sprite collided with.
We can iterate over that list with a for loop to do something with each sprite that had a collision. This means we can detect the user hitting multiple coins at once if we had them placed close together.
In order to do this, and remove the coin sprites when the player hits them, we will add this to the on_update
function.
coin_hit_list = arcade.check_for_collision_with_list(
self.player_sprite, self.coin_list
)
for coin in coin_hit_list:
coin.remove_from_sprite_lists()
We use this arcade.BasicSprite.remove_from_sprite_lists()
function in order to ensure our Sprite is completely
removed from all SpriteLists it was a part of.
Source Code
1"""
2Platformer Game
3
4python -m arcade.examples.platform_tutorial.08_coins
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 def setup(self):
57 """Set up the game here. Call this function to restart the game."""
58 self.player_texture = arcade.load_texture(
59 ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
60 )
61
62 self.player_sprite = arcade.Sprite(self.player_texture)
63 self.player_sprite.center_x = 64
64 self.player_sprite.center_y = 128
65
66 self.player_list = arcade.SpriteList()
67 self.player_list.append(self.player_sprite)
68
69 self.wall_list = arcade.SpriteList(use_spatial_hash=True)
70 self.coin_list = arcade.SpriteList(use_spatial_hash=True)
71
72 # Create the ground
73 # This shows using a loop to place multiple sprites horizontally
74 for x in range(0, 1250, 64):
75 wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
76 wall.center_x = x
77 wall.center_y = 32
78 self.wall_list.append(wall)
79
80 # Put some crates on the ground
81 # This shows using a coordinate list to place sprites
82 coordinate_list = [[512, 96], [256, 96], [768, 96]]
83
84 for coordinate in coordinate_list:
85 # Add a crate on the ground
86 wall = arcade.Sprite(
87 ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
88 )
89 wall.position = coordinate
90 self.wall_list.append(wall)
91
92 # Add coins to the world
93 for x in range(128, 1250, 256):
94 coin = arcade.Sprite(":resources:images/items/coinGold.png", scale=COIN_SCALING)
95 coin.center_x = x
96 coin.center_y = 96
97 self.coin_list.append(coin)
98
99 # Create a Platformer Physics Engine, this will handle moving our
100 # player as well as collisions between the player sprite and
101 # whatever SpriteList we specify for the walls.
102 # It is important to supply static to the walls parameter. There is a
103 # platforms parameter that is intended for moving platforms.
104 # If a platform is supposed to move, and is added to the walls list,
105 # it will not be moved.
106 self.physics_engine = arcade.PhysicsEnginePlatformer(
107 self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
108 )
109
110 # Initialize our camera, setting a viewport the size of our window.
111 self.camera = arcade.camera.Camera2D()
112
113 self.background_color = arcade.csscolor.CORNFLOWER_BLUE
114
115 def on_draw(self):
116 """Render the screen."""
117
118 # Clear the screen to the background color
119 self.clear()
120
121 # Activate our camera before drawing
122 self.camera.use()
123
124 # Draw our sprites
125 self.player_list.draw()
126 self.wall_list.draw()
127 self.coin_list.draw()
128
129 def on_update(self, delta_time):
130 """Movement and Game Logic"""
131
132 # Move the player using our physics engine
133 self.physics_engine.update()
134
135 # See if we hit any coins
136 coin_hit_list = arcade.check_for_collision_with_list(
137 self.player_sprite, self.coin_list
138 )
139
140 # Loop through each coin we hit (if any) and remove it
141 for coin in coin_hit_list:
142 # Remove the coin
143 coin.remove_from_sprite_lists()
144
145 # Center our camera on the player
146 self.camera.position = self.player_sprite.position
147
148 def on_key_press(self, key, modifiers):
149 """Called whenever a key is pressed."""
150
151 if key == arcade.key.ESCAPE:
152 self.setup()
153
154 if key == arcade.key.UP or key == arcade.key.W:
155 if self.physics_engine.can_jump():
156 self.player_sprite.change_y = PLAYER_JUMP_SPEED
157
158 if key == arcade.key.LEFT or key == arcade.key.A:
159 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
160 elif key == arcade.key.RIGHT or key == arcade.key.D:
161 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
162
163 def on_key_release(self, key, modifiers):
164 """Called whenever a key is released."""
165
166 if key == arcade.key.LEFT or key == arcade.key.A:
167 self.player_sprite.change_x = 0
168 elif key == arcade.key.RIGHT or key == arcade.key.D:
169 self.player_sprite.change_x = 0
170
171
172def main():
173 """Main function"""
174 window = GameView()
175 window.setup()
176 arcade.run()
177
178
179if __name__ == "__main__":
180 main()
Run This Chapter
python -m arcade.examples.platform_tutorial.08_coins