Step 8 - Display The Score#

Now that we can collect coins and get points, we need a way to display the score on the screen.

This process is a little bit more complex than just drawing some text at an X and Y location. For properly drawing text, or any GUI elements, we need to use a separate camera than the one we use to draw the rest of our scene.

This is because we are scrolling around the main game camera, but we want our GUI elements to stay still. Using a second camera lets us do this.

As an example, if we were not to use a second camera, and instead draw on the same camera as our scene. We would need to offset the position that we draw our text at by position of the camera. This might be easier if you’re only displaying one thing, but if you have a lot of GUI elements this could get out of hand.

First start by creating the new GUI camera and the score variables in the __init__ function.

Display The Score - The init method#
        self.camera = None

        # A Camera that can be used to draw GUI elements
        self.gui_camera = None

Then we can initialize them in the setup function. We reset the score to 0 here because this function is intended to fully reset the game back to it’s starting state.

Display The Score - The setup method#
        self.camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))

        # Set up the GUI Camera
        self.gui_camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))

Then in our on_draw function we can first draw our scene like normal, and then switch to the GUI camera, and then finally draw our text.

Display The Score - The on_draw method#
        )

    def on_draw(self):
        """Render the screen."""

        # Clear the screen to the background color
        self.clear()

        # Activate the game camera
        self.camera.use()

        # Draw our Scene
        self.scene.draw()

        # Activate the GUI camera before drawing GUI elements
        self.gui_camera.use()

        # Draw our score on the screen, scrolling it with the viewport
        score_text = f"Score: {self.score}"
        arcade.draw_text(
            score_text,
            10,
            10,
            arcade.csscolor.WHITE,

Lastly in the on_update function we just need to update the score when a player collects a coin:

Display The Score - The on_update method#
        )

        # Loop through each coin we hit (if any) and remove it
        for coin in coin_hit_list:
            # Remove the coin
            coin.remove_from_sprite_lists()
            # Play a sound
            arcade.play_sound(self.collect_coin_sound)

Note

You might also want to add:

Source Code#

Display The Score#
  1"""
  2Platformer Game
  3
  4python -m arcade.examples.platform_tutorial.08_score
  5"""
  6import arcade
  7
  8# Constants
  9SCREEN_WIDTH = 1000
 10SCREEN_HEIGHT = 650
 11SCREEN_TITLE = "Platformer"
 12
 13# Constants used to scale our sprites from their original size
 14CHARACTER_SCALING = 1
 15TILE_SCALING = 0.5
 16COIN_SCALING = 0.5
 17
 18# Movement speed of player, in pixels per frame
 19PLAYER_MOVEMENT_SPEED = 5
 20GRAVITY = 1
 21PLAYER_JUMP_SPEED = 20
 22
 23
 24class MyGame(arcade.Window):
 25    """
 26    Main application class.
 27    """
 28
 29    def __init__(self):
 30
 31        # Call the parent class and set up the window
 32        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 33
 34        # Our Scene Object
 35        self.scene = None
 36
 37        # Separate variable that holds the player sprite
 38        self.player_sprite = None
 39
 40        # Our physics engine
 41        self.physics_engine = None
 42
 43        # A Camera that can be used for scrolling the screen
 44        self.camera = None
 45
 46        # A Camera that can be used to draw GUI elements
 47        self.gui_camera = None
 48
 49        # Keep track of the score
 50        self.score = 0
 51
 52        # Load sounds
 53        self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
 54        self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
 55
 56        arcade.set_background_color(arcade.csscolor.CORNFLOWER_BLUE)
 57
 58    def setup(self):
 59        """Set up the game here. Call this function to restart the game."""
 60
 61        # Set up the Game Camera
 62        self.camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))
 63
 64        # Set up the GUI Camera
 65        self.gui_camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))
 66
 67        # Keep track of the score
 68        self.score = 0
 69
 70        # Initialize Scene
 71        self.scene = arcade.Scene()
 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 = 96
 78        self.scene.add_sprite("Player", 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.scene.add_sprite("Walls", wall)
 87
 88        # Put some crates on the ground
 89        # This shows using a coordinate list to place sprites
 90        coordinate_list = [[512, 96], [256, 96], [768, 96]]
 91
 92        for coordinate in coordinate_list:
 93            # Add a crate on the ground
 94            wall = arcade.Sprite(
 95                ":resources:images/tiles/boxCrate_double.png", TILE_SCALING
 96            )
 97            wall.position = coordinate
 98            self.scene.add_sprite("Walls", 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.scene.add_sprite("Coins", coin)
106
107        # Create the 'physics engine'
108        self.physics_engine = arcade.PhysicsEnginePlatformer(
109            self.player_sprite, gravity_constant=GRAVITY, walls=self.scene["Walls"]
110        )
111
112    def on_draw(self):
113        """Render the screen."""
114
115        # Clear the screen to the background color
116        self.clear()
117
118        # Activate the game camera
119        self.camera.use()
120
121        # Draw our Scene
122        self.scene.draw()
123
124        # Activate the GUI camera before drawing GUI elements
125        self.gui_camera.use()
126
127        # Draw our score on the screen, scrolling it with the viewport
128        score_text = f"Score: {self.score}"
129        arcade.draw_text(
130            score_text,
131            10,
132            10,
133            arcade.csscolor.WHITE,
134            18,
135        )
136
137    def on_key_press(self, key, modifiers):
138        """Called whenever a key is pressed."""
139
140        if key == arcade.key.UP or key == arcade.key.W:
141            if self.physics_engine.can_jump():
142                self.player_sprite.change_y = PLAYER_JUMP_SPEED
143                arcade.play_sound(self.jump_sound)
144        elif key == arcade.key.LEFT or key == arcade.key.A:
145            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
146        elif key == arcade.key.RIGHT or key == arcade.key.D:
147            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
148
149    def on_key_release(self, key, modifiers):
150        """Called when the user releases a key."""
151
152        if key == arcade.key.LEFT or key == arcade.key.A:
153            self.player_sprite.change_x = 0
154        elif key == arcade.key.RIGHT or key == arcade.key.D:
155            self.player_sprite.change_x = 0
156
157    def center_camera_to_player(self):
158        screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2)
159        screen_center_y = self.player_sprite.center_y - (
160            self.camera.viewport_height / 2
161        )
162        if screen_center_x < 0:
163            screen_center_x = 0
164        if screen_center_y < 0:
165            screen_center_y = 0
166        player_centered = screen_center_x, screen_center_y
167
168        self.camera.move_to(player_centered)
169
170    def on_update(self, delta_time):
171        """Movement and game logic"""
172
173        # Move the player with the physics engine
174        self.physics_engine.update()
175
176        # See if we hit any coins
177        coin_hit_list = arcade.check_for_collision_with_list(
178            self.player_sprite, self.scene["Coins"]
179        )
180
181        # Loop through each coin we hit (if any) and remove it
182        for coin in coin_hit_list:
183            # Remove the coin
184            coin.remove_from_sprite_lists()
185            # Play a sound
186            arcade.play_sound(self.collect_coin_sound)
187            # Add one to the score
188            self.score += 1
189
190        # Position the camera
191        self.center_camera_to_player()
192
193
194def main():
195    """Main function"""
196    window = MyGame()
197    window.setup()
198    arcade.run()
199
200
201if __name__ == "__main__":
202    main()