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