第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