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#

        # A Camera that can be used for scrolling the screen
        self.camera = None

        # A Camera that can be used to draw GUI elements

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#

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

        # Set up the GUI Camera

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#
        self.physics_engine = arcade.PhysicsEnginePlatformer(
            self.player_sprite, gravity_constant=GRAVITY, walls=self.scene["Walls"]
        )

    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,

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#
        coin_hit_list = arcade.check_for_collision_with_list(
            self.player_sprite, self.scene["Coins"]
        )

        # 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()

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