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.

Display The Score
  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:

Explore On Your Own