第11步-使用场景#
到目前为止,我们的游戏中有三个SpriteList。一个给我们的玩家,一个给我们的墙(地面和盒子),一个给我们的硬币。这仍然是可控的,但随着我们游戏的发展呢?你也许可以想象,一场比赛可能会有数百名SpriteList。仅使用我们当前的方法,我们就必须跟踪每个变量,并确保以正确的顺序绘制它们。
Arade提供了一种更好的方法来处理此问题, arcade.Scene
班级。这个类将为我们保存所有的精灵列表,允许我们创建新的精灵列表,更改它们被吸引的顺序,等等。在后面的章节中,我们将使用一个特殊的函数从地图编辑器工具中加载地图,并根据地图自动创建场景。
在本章结束时,您将得到与之前相同的结果,但使用场景对象的代码将略有不同。
首先,我们可以将所有SpriteList变量从 __init__
并将它们替换为On变量以保存场景对象:
self.scene = None
现在在我们的最顶端 setup
函数,我们可以通过执行以下操作来初始化场景:
self.scene = arcade.Scene()
接下来,我们将删除中的行 setup
它初始化了我们的球员精灵列表,该行看起来是这样的:
self.player_list = arcade.SpriteList()
然后,不是使用以下命令将我们的播放器添加到SpriteList self.player_sprite.append()
。我们会将玩家直接添加到场景中:
self.player_sprite = arcade.Sprite(self.player_texture)
self.player_sprite.center_x = 64
self.player_sprite.center_y = 128
self.scene.add_sprite("Player", self.player_sprite)
让我们分析一下当我们这样做时会发生什么 arcade.Scene.add_sprite()
。它的第一个参数是一个字符串,它定义了我们要向其添加Sprite的层的名称。这可以是现有的层,也可以是新的层。如果层已经存在,精灵将被添加到它,如果它不存在,场景将自动创建它。在引擎盖下,层只是一个带有名称的SpriteList。因此,当我们指定 Player
作为我们的一层。场景正在创建一个新的SpriteList,给它命名,然后将我们的球员Sprite添加到其中。
接下来,我们将用以下函数替换WALL和COUNT SpriteList的初始化:
self.scene.add_sprite_list("Walls", use_spatial_hash=True)
self.scene.add_sprite_list("Coins", use_spatial_hash=True)
在这里,我们采取的方法与我们对我们的 Player
一层。对于我们的球员,我们只是直接添加了一杯雪碧。这里我们初始化了新的空层,名为 Walls
和 Coins
。这种方法的优点是,我们可以指定该层应该使用空间散列,就像我们之前为那些SpriteList指定的那样。
现在,当我们使用 add_sprite
函数之后,这些精灵将被添加到这些现有的层中。
为了将Sprite添加到这些组件中,让我们修改 self.wall_list.append()
For循环中的函数,用于将我们的墙和硬币放置在 setup
功能。我们实际上更改这些循环的唯一部分是将其添加到SpriteList的最后一行,但我已经包括了这些循环,这样您就可以看到它应该在哪里更改。
# Create the ground
for x in range(0, 1250, 64):
wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
wall.center_x = x
wall.center_y = 32
self.scene.add_sprite("Walls", wall)
# Putting Crates on the Ground
coordinate_list = [[512, 96], [256, 96], [768, 96]]
for coordinate in coordinate_li
wall = arcade.Sprite(
":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
)
wall.position = coordinate
self.scene.add_sprite("Walls", wall)
# Add coins to the world
for x in range(128, 1250, 256):
coin = arcade.Sprite(":resources:images/items/coinGold.png", scale=COIN_SCALING)
coin.center_x = x
coin.center_y = 96
self.scene.add_sprite("Coins", coin)
接下来我们需要做的是修复我们的物理引擎。如果您还记得在第4章,我们添加了一个物理引擎,并将我们的WALL精灵列表发送到 walls
参数。
我们需要将PhysicsEngPlatformer初始化修改为:
self.physics_engine = arcade.PhysicsEnginePlatformer(
self.player_sprite, walls=self.scene["Walls"], gravity_constant=GRAVITY
)
这与以前基本相同,但我们从场景中删除了墙SpriteList。如果您熟悉Python词典,请参阅 arcade.Scene
类可以以非常类似的方式进行交互。通过将名称放在方括号中传递给场景,可以获取场景中的任何特定SpriteList。
我们还需要更改我们的 arcade.check_for_collision_with_list()
中的函数 on_update
我们用它来获得我们命中的硬币来使用这个新语法。
coin_hit_list = arcade.check_for_collision_with_list(
self.player_sprite, self.scene["Coins"]
)
我们需要做的最后一件事是更新我们的 on_draw
功能。在这里,我们将删除所有SpriteList绘制,并用绘制我们的场景的一行代替它们。
self.scene.draw()
备注
确保在我们的世界摄像头被激活之后和我们的图形用户界面摄像头被激活之前保存它。如果在激活图形用户界面摄像头的情况下绘制场景,则以播放器为中心和滚动将不起作用。
源代码#
1"""
2Platformer Game
3
4python -m arcade.examples.platform_tutorial.11_scene
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 # Replacing all of our SpriteLists with a Scene variable
40 self.scene = None
41
42 # A variable to store our camera object
43 self.camera = None
44
45 # A variable to store our gui camera object
46 self.gui_camera = None
47
48 # This variable will store our score as an integer.
49 self.score = 0
50
51 # This variable will store the text for score that we will draw to the screen.
52 self.score_text = None
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 def setup(self):
59 """Set up the game here. Call this function to restart the game."""
60 self.scene = arcade.Scene()
61
62 self.player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
63
64 self.player_sprite = arcade.Sprite(self.player_texture)
65 self.player_sprite.center_x = 64
66 self.player_sprite.center_y = 128
67 self.scene.add_sprite("Player", self.player_sprite)
68
69 self.scene.add_sprite_list("Walls", use_spatial_hash=True)
70 self.scene.add_sprite_list("Coins", use_spatial_hash=True)
71
72 # Create the ground
73 # This shows using a loop to place multiple sprites horizontally
74 for x in range(0, 1250, 64):
75 wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
76 wall.center_x = x
77 wall.center_y = 32
78 self.scene.add_sprite("Walls", wall)
79
80 # Put some crates on the ground
81 # This shows using a coordinate list to place sprites
82 coordinate_list = [[512, 96], [256, 96], [768, 96]]
83
84 for coordinate in coordinate_list:
85 # Add a crate on the ground
86 wall = arcade.Sprite(
87 ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
88 )
89 wall.position = coordinate
90 self.scene.add_sprite("Walls", wall)
91
92 # Add coins to the world
93 for x in range(128, 1250, 256):
94 coin = arcade.Sprite(":resources:images/items/coinGold.png", scale=COIN_SCALING)
95 coin.center_x = x
96 coin.center_y = 96
97 self.scene.add_sprite("Coins", coin)
98
99 # Create a Platformer Physics Engine, this will handle moving our
100 # player as well as collisions between the player sprite and
101 # whatever SpriteList we specify for the walls.
102 # It is important to supply static to the walls parameter. There is a
103 # platforms parameter that is intended for moving platforms.
104 # If a platform is supposed to move, and is added to the walls list,
105 # it will not be moved.
106 self.physics_engine = arcade.PhysicsEnginePlatformer(
107 self.player_sprite, walls=self.scene["Walls"], gravity_constant=GRAVITY
108 )
109
110 # Initialize our camera, setting a viewport the size of our window.
111 self.camera = arcade.camera.Camera2D()
112
113 # Initialize our gui camera, initial settings are the same as our world camera.
114 self.gui_camera = arcade.camera.Camera2D()
115
116 # Reset our score to 0
117 self.score = 0
118
119 # Initialize our arcade.Text object for score
120 self.score_text = arcade.Text(f"Score: {self.score}", x=0, y=5)
121
122 self.background_color = arcade.csscolor.CORNFLOWER_BLUE
123
124 def on_draw(self):
125 """Render the screen."""
126
127 # Clear the screen to the background color
128 self.clear()
129
130 # Activate our camera before drawing
131 self.camera.use()
132
133 # Draw our Scene
134 self.scene.draw()
135
136 # Activate our GUI camera
137 self.gui_camera.use()
138
139 # Draw our Score
140 self.score_text.draw()
141
142 def on_update(self, delta_time):
143 """Movement and Game Logic"""
144
145 # Move the player using our physics engine
146 self.physics_engine.update()
147
148 # See if we hit any coins
149 coin_hit_list = arcade.check_for_collision_with_list(
150 self.player_sprite, self.scene["Coins"]
151 )
152
153 # Loop through each coin we hit (if any) and remove it
154 for coin in coin_hit_list:
155 # Remove the coin
156 coin.remove_from_sprite_lists()
157 arcade.play_sound(self.collect_coin_sound)
158 self.score += 75
159 self.score_text.text = f"Score: {self.score}"
160
161 # Center our camera on the player
162 self.camera.position = self.player_sprite.position
163
164 def on_key_press(self, key, modifiers):
165 """Called whenever a key is pressed."""
166
167 if key == arcade.key.ESCAPE:
168 self.setup()
169
170 if key == arcade.key.UP or key == arcade.key.W:
171 if self.physics_engine.can_jump():
172 self.player_sprite.change_y = PLAYER_JUMP_SPEED
173 arcade.play_sound(self.jump_sound)
174
175 if key == arcade.key.LEFT or key == arcade.key.A:
176 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
177 elif key == arcade.key.RIGHT or key == arcade.key.D:
178 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
179
180 def on_key_release(self, key, modifiers):
181 """Called whenever a key is released."""
182
183 if key == arcade.key.LEFT or key == arcade.key.A:
184 self.player_sprite.change_x = 0
185 elif key == arcade.key.RIGHT or key == arcade.key.D:
186 self.player_sprite.change_x = 0
187
188
189def main():
190 """Main function"""
191 window = MyGame()
192 window.setup()
193 arcade.run()
194
195
196if __name__ == "__main__":
197 main()
运行本章#
python -m arcade.examples.platform_tutorial.11_scene