Step 7 - Display The Score¶
Now that we can collect coins and get points, we need a way to display the score on the screen.
This is a bit more complex
than just drawing the score at the same x, y location every time because
we have to “scroll” the score right with the player if we have a scrolling
screen. To do this, we just add in the view_bottom
and view_left
coordinates.
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 # Keep track of the score
56 self.score = 0
57
58 # Load sounds
59 self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
60 self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
61
62 arcade.set_background_color(arcade.csscolor.CORNFLOWER_BLUE)
63
64 def setup(self):
65 """ Set up the game here. Call this function to restart the game. """
66
67 # Used to keep track of our scrolling
68 self.view_bottom = 0
69 self.view_left = 0
70
71 # Keep track of the score
72 self.score = 0
73
74 # Create the Sprite lists
75 self.player_list = arcade.SpriteList()
76 self.wall_list = arcade.SpriteList()
77 self.coin_list = arcade.SpriteList()
78
79 # Set up the player, specifically placing it at these coordinates.
80 image_source = ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
81 self.player_sprite = arcade.Sprite(image_source, CHARACTER_SCALING)
82 self.player_sprite.center_x = 64
83 self.player_sprite.center_y = 96
84 self.player_list.append(self.player_sprite)
85
86 # Create the ground
87 # This shows using a loop to place multiple sprites horizontally
88 for x in range(0, 1250, 64):
89 wall = arcade.Sprite(":resources:images/tiles/grassMid.png", TILE_SCALING)
90 wall.center_x = x
91 wall.center_y = 32
92 self.wall_list.append(wall)
93
94 # Put some crates on the ground
95 # This shows using a coordinate list to place sprites
96 coordinate_list = [[512, 96],
97 [256, 96],
98 [768, 96]]
99
100 for coordinate in coordinate_list:
101 # Add a crate on the ground
102 wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", TILE_SCALING)
103 wall.position = coordinate
104 self.wall_list.append(wall)
105
106 # Use a loop to place some coins for our character to pick up
107 for x in range(128, 1250, 256):
108 coin = arcade.Sprite(":resources:images/items/coinGold.png", COIN_SCALING)
109 coin.center_x = x
110 coin.center_y = 96
111 self.coin_list.append(coin)
112
113 # Create the 'physics engine'
114 self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite,
115 self.wall_list,
116 GRAVITY)
117
118 def on_draw(self):
119 """ Render the screen. """
120
121 # Clear the screen to the background color
122 arcade.start_render()
123
124 # Draw our sprites
125 self.wall_list.draw()
126 self.coin_list.draw()
127 self.player_list.draw()
128
129 # Draw our score on the screen, scrolling it with the viewport
130 score_text = f"Score: {self.score}"
131 arcade.draw_text(score_text, 10 + self.view_left, 10 + self.view_bottom,
132 arcade.csscolor.WHITE, 18)
133
134 def on_key_press(self, key, modifiers):
135 """Called whenever a key is pressed. """
136
137 if key == arcade.key.UP or key == arcade.key.W:
138 if self.physics_engine.can_jump():
139 self.player_sprite.change_y = PLAYER_JUMP_SPEED
140 arcade.play_sound(self.jump_sound)
141 elif key == arcade.key.LEFT or key == arcade.key.A:
142 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
143 elif key == arcade.key.RIGHT or key == arcade.key.D:
144 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
145
146 def on_key_release(self, key, modifiers):
147 """Called when the user releases a key. """
148
149 if key == arcade.key.LEFT or key == arcade.key.A:
150 self.player_sprite.change_x = 0
151 elif key == arcade.key.RIGHT or key == arcade.key.D:
152 self.player_sprite.change_x = 0
153
154 def on_update(self, delta_time):
155 """ Movement and game logic """
156
157 # Move the player with the physics engine
158 self.physics_engine.update()
159
160 # See if we hit any coins
161 coin_hit_list = arcade.check_for_collision_with_list(self.player_sprite,
162 self.coin_list)
163
164 # Loop through each coin we hit (if any) and remove it
165 for coin in coin_hit_list:
166 # Remove the coin
167 coin.remove_from_sprite_lists()
168 # Play a sound
169 arcade.play_sound(self.collect_coin_sound)
170 # Add one to the score
171 self.score += 1
172
173 # --- Manage Scrolling ---
174
175 # Track if we need to change the viewport
176
177 changed = False
178
179 # Scroll left
180 left_boundary = self.view_left + LEFT_VIEWPORT_MARGIN
181 if self.player_sprite.left < left_boundary:
182 self.view_left -= left_boundary - self.player_sprite.left
183 changed = True
184
185 # Scroll right
186 right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_VIEWPORT_MARGIN
187 if self.player_sprite.right > right_boundary:
188 self.view_left += self.player_sprite.right - right_boundary
189 changed = True
190
191 # Scroll up
192 top_boundary = self.view_bottom + SCREEN_HEIGHT - TOP_VIEWPORT_MARGIN
193 if self.player_sprite.top > top_boundary:
194 self.view_bottom += self.player_sprite.top - top_boundary
195 changed = True
196
197 # Scroll down
198 bottom_boundary = self.view_bottom + BOTTOM_VIEWPORT_MARGIN
199 if self.player_sprite.bottom < bottom_boundary:
200 self.view_bottom -= bottom_boundary - self.player_sprite.bottom
201 changed = True
202
203 if changed:
204 # Only scroll to integers. Otherwise we end up with pixels that
205 # don't line up on the screen
206 self.view_bottom = int(self.view_bottom)
207 self.view_left = int(self.view_left)
208
209 # Do the scrolling
210 arcade.set_viewport(self.view_left,
211 SCREEN_WIDTH + self.view_left,
212 self.view_bottom,
213 SCREEN_HEIGHT + self.view_bottom)
214
215
216def main():
217 """ Main method """
218 window = MyGame()
219 window.setup()
220 arcade.run()
221
222
223if __name__ == "__main__":
224 main()
Note
You might also want to add:
A count of how many coins are left to be collected.
Number of lives left.
A timer: On-Screen Timer
This example shows how to add an FPS timer: Draw Moving Sprites Stress Test
Explore On Your Own¶
Practice creating your own layout with different tiles.
Add background images. See Using a Background Image
Add moving platforms. See Moving Platforms
Change the character image based on the direction she is facing. See Sprite: Face Left or Right
Add instruction and game over screens.