Work with levels and a tiled map#
sprite_tiled_map_with_levels.py#
1"""
2Load a Tiled map file with Levels
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_with_levels
9"""
10import time
11
12import arcade
13
14TILE_SPRITE_SCALING = 0.5
15PLAYER_SCALING = 0.6
16
17SCREEN_WIDTH = 800
18SCREEN_HEIGHT = 600
19SCREEN_TITLE = "Sprite Tiled Map with Levels Example"
20SPRITE_PIXEL_SIZE = 128
21GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SPRITE_SCALING
22
23# How many pixels to keep as a minimum margin between the character
24# and the edge of the screen.
25VIEWPORT_MARGIN_TOP = 60
26VIEWPORT_MARGIN_BOTTOM = 60
27VIEWPORT_RIGHT_MARGIN = 270
28VIEWPORT_LEFT_MARGIN = 270
29
30# Physics
31MOVEMENT_SPEED = 5
32JUMP_SPEED = 23
33GRAVITY = 1.1
34
35
36class MyGame(arcade.Window):
37 """Main application class."""
38
39 def __init__(self):
40 """
41 Initializer
42 """
43 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
44
45 # Tilemap Object
46 self.tile_map = None
47
48 # Sprite lists
49 self.player_list = None
50
51 # Set up the player
52 self.score = 0
53 self.player_sprite = None
54
55 self.physics_engine = None
56 self.view_left = 0
57 self.view_bottom = 0
58 self.end_of_map = 0
59 self.game_over = False
60 self.last_time = None
61 self.frame_count = 0
62 self.fps_message = None
63
64 self.level = 1
65 self.max_level = 2
66
67 def setup(self):
68 """Set up the game and initialize the variables."""
69
70 # Sprite lists
71 self.player_list = arcade.SpriteList()
72
73 # Set up the player
74 self.player_sprite = arcade.Sprite(
75 ":resources:images/animated_characters/female_person/femalePerson_idle.png",
76 PLAYER_SCALING,
77 )
78
79 # Starting position of the player
80 self.player_sprite.center_x = 128
81 self.player_sprite.center_y = 64
82 self.player_list.append(self.player_sprite)
83
84 self.load_level(self.level)
85
86 self.game_over = False
87
88 def load_level(self, level):
89 # layer_options = {"Platforms": {"use_spatial_hash": True}}
90
91 # Read in the tiled map
92 self.tile_map = arcade.load_tilemap(
93 f":resources:tiled_maps/level_{level}.json", scaling=TILE_SPRITE_SCALING
94 )
95
96 # --- Walls ---
97
98 # Calculate the right edge of the my_map in pixels
99 self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
100
101 self.physics_engine = arcade.PhysicsEnginePlatformer(
102 self.player_sprite,
103 self.tile_map.sprite_lists["Platforms"],
104 gravity_constant=GRAVITY,
105 )
106
107 # --- Other stuff
108 # Set the background color
109 if self.tile_map.background_color:
110 arcade.set_background_color(self.tile_map.background_color)
111
112 # Set the view port boundaries
113 # These numbers set where we have 'scrolled' to.
114 self.view_left = 0
115 self.view_bottom = 0
116
117 def on_draw(self):
118 """
119 Render the screen.
120 """
121
122 self.frame_count += 1
123
124 # This command has to happen before we start drawing
125 self.clear()
126
127 # Draw all the sprites.
128 self.player_list.draw()
129 self.tile_map.sprite_lists["Platforms"].draw()
130
131 if self.last_time and self.frame_count % 60 == 0:
132 fps = 1.0 / (time.time() - self.last_time) * 60
133 self.fps_message = f"FPS: {fps:5.0f}"
134
135 if self.fps_message:
136 arcade.draw_text(
137 self.fps_message,
138 self.view_left + 10,
139 self.view_bottom + 40,
140 arcade.color.BLACK,
141 14,
142 )
143
144 if self.frame_count % 60 == 0:
145 self.last_time = time.time()
146
147 # Put the text on the screen.
148 # Adjust the text position based on the view port so that we don't
149 # scroll the text too.
150 distance = self.player_sprite.right
151 output = f"Distance: {distance:.0f}"
152 arcade.draw_text(
153 output, self.view_left + 10, self.view_bottom + 20, arcade.color.BLACK, 14
154 )
155
156 if self.game_over:
157 arcade.draw_text(
158 "Game Over",
159 self.view_left + 200,
160 self.view_bottom + 200,
161 arcade.color.BLACK,
162 30,
163 )
164
165 def on_key_press(self, key, modifiers):
166 """
167 Called whenever the mouse moves.
168 """
169 if key == arcade.key.UP:
170 if self.physics_engine.can_jump():
171 self.player_sprite.change_y = JUMP_SPEED
172 elif key == arcade.key.LEFT:
173 self.player_sprite.change_x = -MOVEMENT_SPEED
174 elif key == arcade.key.RIGHT:
175 self.player_sprite.change_x = MOVEMENT_SPEED
176
177 def on_key_release(self, key, modifiers):
178 """
179 Called when the user presses a mouse button.
180 """
181 if key == arcade.key.LEFT or key == arcade.key.RIGHT:
182 self.player_sprite.change_x = 0
183
184 def on_update(self, delta_time):
185 """Movement and game logic"""
186
187 if self.player_sprite.right >= self.end_of_map:
188 if self.level < self.max_level:
189 self.level += 1
190 self.load_level(self.level)
191 self.player_sprite.center_x = 128
192 self.player_sprite.center_y = 64
193 self.player_sprite.change_x = 0
194 self.player_sprite.change_y = 0
195 else:
196 self.game_over = True
197
198 # Call update on all sprites (The sprites don't do much in this
199 # example though.)
200 if not self.game_over:
201 self.physics_engine.update()
202
203 # --- Manage Scrolling ---
204
205 # Track if we need to change the view port
206
207 changed = False
208
209 # Scroll left
210 left_bndry = self.view_left + VIEWPORT_LEFT_MARGIN
211 if self.player_sprite.left < left_bndry:
212 self.view_left -= left_bndry - self.player_sprite.left
213 changed = True
214
215 # Scroll right
216 right_bndry = self.view_left + SCREEN_WIDTH - VIEWPORT_RIGHT_MARGIN
217 if self.player_sprite.right > right_bndry:
218 self.view_left += self.player_sprite.right - right_bndry
219 changed = True
220
221 # Scroll up
222 top_bndry = self.view_bottom + SCREEN_HEIGHT - VIEWPORT_MARGIN_TOP
223 if self.player_sprite.top > top_bndry:
224 self.view_bottom += self.player_sprite.top - top_bndry
225 changed = True
226
227 # Scroll down
228 bottom_bndry = self.view_bottom + VIEWPORT_MARGIN_BOTTOM
229 if self.player_sprite.bottom < bottom_bndry:
230 self.view_bottom -= bottom_bndry - self.player_sprite.bottom
231 changed = True
232
233 # If we need to scroll, go ahead and do it.
234 if changed:
235 self.view_left = int(self.view_left)
236 self.view_bottom = int(self.view_bottom)
237 arcade.set_viewport(
238 self.view_left,
239 SCREEN_WIDTH + self.view_left,
240 self.view_bottom,
241 SCREEN_HEIGHT + self.view_bottom,
242 )
243
244
245def main():
246 window = MyGame()
247 window.setup()
248 arcade.run()
249
250
251if __name__ == "__main__":
252 main()