第12步-从地图编辑器加载地图#
在本章中,我们将开始使用一个名为 Tiled 。平铺是一个流行的2D地图编辑器,它可以与任何游戏引擎一起使用,但Arade有专门的集成来处理平铺。
在本教程中,我们将探讨如何使用Arade的内置功能从切片加载地图 arcade.TileMap
使用Arade附带的内置资源中的一些地图来初始化。我们不会在本教程中介绍如何实际构建地图,但如果您想了解更多有关切片的信息,请查看以下资源:
实际上,您不需要平铺即可继续学习本教程。我们将使用Arade附带的所有预建地图。然而,如果你想尝试自己的地图或改变事物,我建议你去拼贴并熟悉它,它是一个非常有用的2D游戏开发工具。
首先,我们将删除一些代码。也就是说,我们将移除我们的地面、盒子和硬币精灵的创造(我们将留给玩家一个)。继续,并从 setup
功能。
self.scene.add_sprite_list("Walls", use_spatial_hash=True)
self.scene.add_sprite_list("Coins", use_spatial_hash=True)
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)
coordinate_list = [[512, 96], [256, 96], [768, 96]]
for coordinate in coordinate_list:
wall = arcade.Sprite(
":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
)
wall.position = coordinate
self.scene.add_sprite("Walls", wall)
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)
一旦我们开始加载 Mapfile ,这些事情现在将由我们的 Mapfile 自动处理。
为了加载地图,我们将首先在中为其创建一个变量 __init__
:
self.tile_map = None
接下来,我们将把地图加载到 setup
函数,然后使用Arade提供的内置函数从该函数创建场景。这将给我们一个完全基于 Mapfile 自动绘制的场景。此代码将全部放在 setup
功能。
确保替换设置为 self.scene
下面是新的。
layer_options = {
"Platforms": {
"use_spatial_hash": True
}
}
self.tile_map = arcade.load_tilemap(
":resources:tiled_maps/map.json",
scaling=TILE_SCALING,
layer_options=layer_options
)
self.scene = arcade.Scene.from_tilemap(self.tile_map)
这段代码将加载到我们的内置平铺地图中,并自动从它构建场景。这个阶段的场景已经准备好可以绘制了,我们不需要对它做任何其他操作(除了添加我们的球员)。
备注
是什么 layer_options
而这些价值观又从何而来呢?
layer_options
is a special dictionary that can be provided to the load_tilemap
function. This will
send special options for each layer into the map loader. In this example our map has a layer called
Platforms
, and we want to enable spatial hashing on it. Much like we did for our wall
SpriteList
before. For more info on the layer options dictionary and the available keys, check out :class`arcade.TileMap`
在这一点上,我们只剩下一段代码需要更改。在切换到我们的新地图时,您可能已经注意到 layer_options
字典,我们现在有一个名为 Platforms
。在我们之前的场景中,我们将这一层称为 Walls
。在创建物理引擎时,我们需要更新该引用。
在 setup
函数更新物理引擎创建以使用新的 Platforms
层:
self.physics_engine = arcade.PhysicsEnginePlatformer(
self.player_sprite, walls=self.scene["Platforms"], gravity_constant=GRAVITY
)
源代码#
1"""
2Platformer Game
3
4python -m arcade.examples.platform_tutorial.12_tiled
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 # Variable to hold our Tiled Map
40 self.tile_map = None
41
42 # Replacing all of our SpriteLists with a Scene variable
43 self.scene = None
44
45 # A variable to store our camera object
46 self.camera = None
47
48 # A variable to store our gui camera object
49 self.gui_camera = None
50
51 # This variable will store our score as an integer.
52 self.score = 0
53
54 # This variable will store the text for score that we will draw to the screen.
55 self.score_text = None
56
57 # Load sounds
58 self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
59 self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
60
61 def setup(self):
62 """Set up the game here. Call this function to restart the game."""
63 layer_options = {
64 "Platforms": {
65 "use_spatial_hash": True
66 }
67 }
68
69 # Load our TileMap
70 self.tile_map = arcade.load_tilemap(":resources:tiled_maps/map.json", scaling=TILE_SCALING, layer_options=layer_options)
71
72 # Create our Scene Based on the TileMap
73 self.scene = arcade.Scene.from_tilemap(self.tile_map)
74
75 self.player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
76
77 self.player_sprite = arcade.Sprite(self.player_texture)
78 self.player_sprite.center_x = 128
79 self.player_sprite.center_y = 128
80 self.scene.add_sprite("Player", self.player_sprite)
81
82 # Create a Platformer Physics Engine, this will handle moving our
83 # player as well as collisions between the player sprite and
84 # whatever SpriteList we specify for the walls.
85 # It is important to supply static to the walls parameter. There is a
86 # platforms parameter that is intended for moving platforms.
87 # If a platform is supposed to move, and is added to the walls list,
88 # it will not be moved.
89 self.physics_engine = arcade.PhysicsEnginePlatformer(
90 self.player_sprite, walls=self.scene["Platforms"], gravity_constant=GRAVITY
91 )
92
93 # Initialize our camera, setting a viewport the size of our window.
94 self.camera = arcade.camera.Camera2D()
95
96 # Initialize our gui camera, initial settings are the same as our world camera.
97 self.gui_camera = arcade.camera.Camera2D()
98
99 # Reset our score to 0
100 self.score = 0
101
102 # Initialize our arcade.Text object for score
103 self.score_text = arcade.Text(f"Score: {self.score}", x=0, y=5)
104
105 self.background_color = arcade.csscolor.CORNFLOWER_BLUE
106
107 def on_draw(self):
108 """Render the screen."""
109
110 # Clear the screen to the background color
111 self.clear()
112
113 # Activate our camera before drawing
114 self.camera.use()
115
116 # Draw our Scene
117 self.scene.draw()
118
119 # Activate our GUI camera
120 self.gui_camera.use()
121
122 # Draw our Score
123 self.score_text.draw()
124
125 def on_update(self, delta_time):
126 """Movement and Game Logic"""
127
128 # Move the player using our physics engine
129 self.physics_engine.update()
130
131 # See if we hit any coins
132 coin_hit_list = arcade.check_for_collision_with_list(
133 self.player_sprite, self.scene["Coins"]
134 )
135
136 # Loop through each coin we hit (if any) and remove it
137 for coin in coin_hit_list:
138 # Remove the coin
139 coin.remove_from_sprite_lists()
140 arcade.play_sound(self.collect_coin_sound)
141 self.score += 75
142 self.score_text.text = f"Score: {self.score}"
143
144 # Center our camera on the player
145 self.camera.position = self.player_sprite.position
146
147 def on_key_press(self, key, modifiers):
148 """Called whenever a key is pressed."""
149
150 if key == arcade.key.ESCAPE:
151 self.setup()
152
153 if key == arcade.key.UP or key == arcade.key.W:
154 if self.physics_engine.can_jump():
155 self.player_sprite.change_y = PLAYER_JUMP_SPEED
156 arcade.play_sound(self.jump_sound)
157
158 if key == arcade.key.LEFT or key == arcade.key.A:
159 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
160 elif key == arcade.key.RIGHT or key == arcade.key.D:
161 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
162
163 def on_key_release(self, key, modifiers):
164 """Called whenever a key is released."""
165
166 if key == arcade.key.LEFT or key == arcade.key.A:
167 self.player_sprite.change_x = 0
168 elif key == arcade.key.RIGHT or key == arcade.key.D:
169 self.player_sprite.change_x = 0
170
171
172def main():
173 """Main function"""
174 window = MyGame()
175 window.setup()
176 arcade.run()
177
178
179if __name__ == "__main__":
180 main()