Work with loading in a Tiled map file#
Below is a quick example on using a Tiled map. For more information, see:
1"""
2Load a Tiled map file
3
4Artwork from: https://kenney.nl
5Tiled available from: https://www.mapeditor.org/
6
7If Python and Arcade are installed, this example can be run from the command line with:
8python -m arcade.examples.sprite_tiled_map
9"""
10
11from __future__ import annotations
12
13import time
14
15import arcade
16
17TILE_SCALING = 0.5
18PLAYER_SCALING = 1
19
20SCREEN_WIDTH = 800
21SCREEN_HEIGHT = 600
22SCREEN_TITLE = "Sprite Tiled Map Example"
23SPRITE_PIXEL_SIZE = 128
24GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SCALING
25
26# How many pixels to keep as a minimum margin between the character
27# and the edge of the screen.
28VIEWPORT_MARGIN_TOP = 60
29VIEWPORT_MARGIN_BOTTOM = 60
30VIEWPORT_RIGHT_MARGIN = 270
31VIEWPORT_LEFT_MARGIN = 270
32
33# Physics
34MOVEMENT_SPEED = 5
35JUMP_SPEED = 23
36GRAVITY = 1.1
37
38
39class MyGame(arcade.Window):
40 """Main application class."""
41
42 def __init__(self):
43 """
44 Initializer
45 """
46 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
47
48 # Tilemap Object
49 self.tile_map = None
50
51 # Sprite lists
52 self.player_list = None
53 self.wall_list = None
54 self.coin_list = None
55
56 # Set up the player
57 self.score = 0
58 self.player_sprite = None
59
60 self.physics_engine = None
61 self.end_of_map = 0
62 self.game_over = False
63 self.last_time = None
64 self.frame_count = 0
65
66 # Cameras
67 self.camera = None
68 self.gui_camera = None
69
70 # Text
71 self.fps_text = arcade.Text(
72 "",
73 start_x=10,
74 start_y=40,
75 color=arcade.color.BLACK,
76 font_size=14
77 )
78 self.distance_text = arcade.Text(
79 "0.0",
80 start_x=10,
81 start_y=20,
82 color=arcade.color.BLACK,
83 font_size=14,
84 )
85
86 def setup(self):
87 """Set up the game and initialize the variables."""
88
89 # Sprite lists
90 self.player_list = arcade.SpriteList()
91
92 # Set up the player
93 self.player_sprite = arcade.Sprite(
94 ":resources:images/animated_characters/female_person/femalePerson_idle.png",
95 scale=PLAYER_SCALING,
96 )
97
98 # Starting position of the player
99 self.player_sprite.center_x = 196
100 self.player_sprite.center_y = 270
101 self.player_list.append(self.player_sprite)
102
103 map_name = ":resources:/tiled_maps/map.json"
104
105 layer_options = {
106 "Platforms": {"use_spatial_hash": True},
107 "Coins": {"use_spatial_hash": True},
108 }
109
110 # Read in the tiled map
111 self.tile_map = arcade.load_tilemap(
112 map_name, layer_options=layer_options, scaling=TILE_SCALING
113 )
114 self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
115
116 # Set wall and coin SpriteLists
117 self.wall_list = self.tile_map.sprite_lists["Platforms"]
118 self.coin_list = self.tile_map.sprite_lists["Coins"]
119
120 # --- Other stuff
121 # Set the background color
122 if self.tile_map.background_color:
123 self.background_color = self.tile_map.background_color
124
125 # Keep player from running through the wall_list layer
126 walls = [self.wall_list, ]
127 self.physics_engine = arcade.PhysicsEnginePlatformer(
128 self.player_sprite, walls, gravity_constant=GRAVITY
129 )
130
131 self.camera = arcade.SimpleCamera()
132 self.gui_camera = arcade.SimpleCamera()
133
134 # Center camera on user
135 self.pan_camera_to_user()
136
137 self.game_over = False
138
139 def on_draw(self):
140 """
141 Render the screen.
142 """
143
144 # This command has to happen before we start drawing
145 self.camera.use()
146 self.clear()
147
148 # Start counting frames
149 self.frame_count += 1
150
151 # Draw all the sprites.
152 self.player_list.draw()
153 self.wall_list.draw()
154 self.coin_list.draw()
155
156 # Activate GUI camera for FPS, distance and hit boxes
157 # This will adjust text position based on viewport
158 self.gui_camera.use()
159
160 # Calculate FPS if conditions are met
161 if self.last_time and self.frame_count % 60 == 0:
162 fps = round(1.0 / (time.time() - self.last_time) * 60)
163 self.fps_text.text = f"FPS: {fps:3d}"
164
165 # Draw FPS text
166 self.fps_text.draw()
167
168 # Get time for every 60 frames
169 if self.frame_count % 60 == 0:
170 self.last_time = time.time()
171
172 # Enable to draw hit boxes
173 # self.wall_list.draw_hit_boxes()
174 # self.wall_list_objects.draw_hit_boxes()
175
176 # Get distance and draw text
177 distance = self.player_sprite.right
178 self.distance_text.text = f"Distance: {distance}"
179 self.distance_text.draw()
180
181 # Draw game over text if condition met
182 if self.game_over:
183 arcade.draw_text(
184 "Game Over",
185 200,
186 200,
187 arcade.color.BLACK,
188 30,
189 )
190
191 def on_key_press(self, key, modifiers):
192 """
193 Called whenever a key is pressed.
194 """
195 if key == arcade.key.UP:
196 if self.physics_engine.can_jump():
197 self.player_sprite.change_y = JUMP_SPEED
198 elif key == arcade.key.LEFT:
199 self.player_sprite.change_x = -MOVEMENT_SPEED
200 elif key == arcade.key.RIGHT:
201 self.player_sprite.change_x = MOVEMENT_SPEED
202
203 def on_key_release(self, key, modifiers):
204 """
205 Called when the user presses a mouse button.
206 """
207 if key == arcade.key.LEFT or key == arcade.key.RIGHT:
208 self.player_sprite.change_x = 0
209
210 def on_update(self, delta_time):
211 """Movement and game logic"""
212
213 if self.player_sprite.right >= self.end_of_map:
214 self.game_over = True
215
216 # Call update on all sprites
217 if not self.game_over:
218 self.physics_engine.update()
219
220 coins_hit = arcade.check_for_collision_with_list(
221 self.player_sprite, self.coin_list
222 )
223 for coin in coins_hit:
224 coin.remove_from_sprite_lists()
225 self.score += 1
226
227 # Pan to the user
228 self.pan_camera_to_user(panning_fraction=0.12)
229
230 def pan_camera_to_user(self, panning_fraction: float = 1.0):
231 """ Manage Scrolling """
232
233 # This spot would center on the user
234 screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2)
235 screen_center_y = self.player_sprite.center_y - (
236 self.camera.viewport_height / 2
237 )
238 if screen_center_x < 0:
239 screen_center_x = 0
240 if screen_center_y < 0:
241 screen_center_y = 0
242 user_centered = screen_center_x, screen_center_y
243
244 self.camera.move_to(user_centered, panning_fraction)
245
246
247def main():
248 window = MyGame()
249 window.setup()
250 arcade.run()
251
252
253if __name__ == "__main__":
254 main()