第10步-添加分数#

我们的游戏开始成型,但我们仍然需要奖励玩家的辛勤工作收集硬币。为了做到这一点,我们将添加一个分数,每次他们收集一枚硬币时,分数都会增加,并在屏幕上显示出来。

在本章中,我们将介绍使用 arcade.Text 对象,以及使用两个照相机在“屏幕空间”中绘制对象和在“世界空间”中绘制对象的技术。

备注

什么是屏幕空间和世界空间?想一想你可能玩过的其他游戏,让我们把它与我们的游戏进行比较。玩家在世界上四处移动,我们根据这个位置滚动相机。这是一个“世界空间”坐标的例子。它们可以扩展到我们的窗口之外,并且需要相应地定位在窗口内。

“屏幕空间”坐标的一个例子是我们的分数指示器。我们会将其绘制在屏幕上,但我们不希望它在相机滚动时在屏幕上移动。为了实现这一点,我们将使用两个不同的相机,并移动世界空间相机,但不移动屏幕空间相机。

在我们的代码中,我们将这个屏幕空间相机称为, gui_camera

让我们继续为我们的新相机添加一个变量,并在 setup 。我们还将为我们的分数添加一个变量。这将只是一个最初设置为0的整数。我们将在这两个文件中设置此项 __init__setup

# Within __init__
self.gui_camera = None
self.score = 0

# Within setup
self.gui_camera = arcade.SimpleCamera(viewport=(0, 0, width, height))
self.score = 0

现在我们可以进入我们的 on_update 函数,当玩家收集一枚硬币时,我们可以增加分数变量。目前,我们将给收集硬币的玩家75分。你可以改变这一点,或者作为练习,尝试添加具有不同点值的不同类型的硬币。在后面的章节中,我们将探索从地图编辑器中动态提供硬币的点值。

# Within on_update
for coin in coin_hit_list:
    coin.remove_from_sprite_lists()
    arcade.play_sound(self.collect_coin_sound)
    self.score += 75

现在我们正在递增分数,我们如何将其绘制到屏幕上?我们将使用我们的图形用户界面摄像头,但到目前为止,我们还没有讨论过在Arade中绘制文本。在Arade中有几种方法可以做到这一点,第一种方法是使用 arcade.draw_text() 功能。这是一个简单的函数,可以直接放入 on_draw 若要绘制文本字符串,请执行以下操作。

然而,这个函数的性能并不是很好,还有一种更好的方法。我们将转而使用 arcade.Text 物体。它们有很多优点,比如不需要在每次绘制文本时重新计算文本,也可以像我们使用Sprite和SpriteList一样批量绘制。稍后我们将探索批量绘制文本。

现在,让我们创建一个 arcade.Text 对象来保存我们的乐谱文本。首先在中创建空变量 __init__ 并在中进行初始化 setup

# Within __init__
self.score_text = None

# Within setup
self.score_text = arcade.Text(f"Score: {self.score}", start_x = 0, start_y = 5)

我们发送到的第一个参数 arcade.Text 是包含我们要绘制的文本的字符串。在我们的示例中,我们提供了一个f字符串,它将我们的值从 self.score 融入到文本中。其他参数定义了绘制文本的左下点。

我已将其设置为在屏幕的左下角绘制。你可以试着把它搬来搬去。

现在,我们需要将此代码添加到我们的 on_draw 函数,以便将其显示在屏幕上。

# Within on_draw
self.gui_camera.use()
self.score_text.draw()

这将在屏幕左下角绘制我们的文本。然而,我们仍然有一个问题,当我们的用户获得新的分数时,我们不会更新文本。为了做到这一点,我们将回到我们的 on_update 函数,在该函数中,当用户收集一枚硬币时,我们增加分数,并向其添加一行:

for coin in coin_hit_list:
    coin.remove_from_sprite_lists()
    arcade.play_sound(self.collect_coin_sound)
    self.score += 75
    self.score_text.text = f"Score: {self.score}"

在这一新行中,我们更新Text对象的实际文本以包含新的分数值。

源代码#

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

运行本章#

python -m arcade.examples.platform_tutorial.10_score