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 arcade
11
12TILE_SPRITE_SCALING = 0.5
13PLAYER_SCALING = 0.6
14
15WINDOW_WIDTH = 1280
16WINDOW_HEIGHT = 720
17WINDOW_TITLE = "Sprite Tiled Map with Levels Example"
18SPRITE_PIXEL_SIZE = 128
19GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SPRITE_SCALING
20CAMERA_PAN_SPEED = 0.15
21
22# Physics
23MOVEMENT_SPEED = 5
24JUMP_SPEED = 23
25GRAVITY = 1.1
26
27
28class GameView(arcade.View):
29 """Main application class."""
30
31 def __init__(self):
32 """
33 Initializer
34 """
35 super().__init__()
36
37 # Tilemap Object
38 self.tile_map = None
39
40 # Sprite lists
41 self.player_list = None
42
43 # Set up the player
44 self.score = 0
45 self.player_sprite = None
46
47 self.physics_engine = None
48 self.end_of_map = 0
49 self.game_over = False
50
51 self.game_camera = None
52 self.gui_camera = None
53 self.camera_bounds = None
54
55 self.fps_text = None
56 self.game_over_text = None
57
58 self.level = 1
59 self.max_level = 2
60
61 def setup(self):
62 """Set up the game and initialize the variables."""
63
64 # Sprite lists
65 self.player_list = arcade.SpriteList()
66
67 # Set up the player
68 self.player_sprite = arcade.Sprite(
69 ":resources:images/animated_characters/female_person/femalePerson_idle.png",
70 scale=PLAYER_SCALING,
71 )
72
73 self.game_camera = arcade.camera.Camera2D()
74 self.gui_camera = arcade.camera.Camera2D()
75
76 self.fps_text = arcade.Text('FPS:', 10, 10, arcade.color.BLACK, 14)
77 self.game_over_text = arcade.Text(
78 'GAME OVER',
79 self.window.center_x,
80 self.window.center_y,
81 arcade.color.BLACK, 30,
82 anchor_x='center',
83 anchor_y='center'
84 )
85
86 # Starting position of the player
87 self.player_sprite.center_x = 128
88 self.player_sprite.center_y = 64
89 self.player_list.append(self.player_sprite)
90
91 self.load_level(self.level)
92
93 self.game_over = False
94
95 def load_level(self, level):
96 # layer_options = {"Platforms": {"use_spatial_hash": True}}
97
98 # Read in the tiled map
99 self.tile_map = arcade.load_tilemap(
100 f":resources:tiled_maps/level_{level}.json", scaling=TILE_SPRITE_SCALING
101 )
102
103 # --- Walls ---
104
105 # Calculate the right edge of the my_map in pixels
106 self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
107
108 self.physics_engine = arcade.PhysicsEnginePlatformer(
109 self.player_sprite,
110 self.tile_map.sprite_lists["Platforms"],
111 gravity_constant=GRAVITY,
112 )
113
114 # --- Other stuff
115 # Set the background color
116 if self.tile_map.background_color:
117 self.window.background_color = self.tile_map.background_color
118
119 max_x = GRID_PIXEL_SIZE * self.tile_map.width
120 max_y = GRID_PIXEL_SIZE * self.tile_map.height
121 limit_y = max_y > self.window.height
122 self.camera_bounds = arcade.LRBT(
123 self.window.width / 2.0,
124 max_x - self.window.width / 2.0,
125 self.window.height / 2.0,
126 max_y - (self.window.height / 2.0 if limit_y else 0.0)
127 )
128
129 # Reset cam
130 self.game_camera.position = self.window.center
131
132 def on_draw(self):
133 """
134 Render the screen.
135 """
136 # This command has to happen before we start drawing
137 self.clear()
138
139 with self.game_camera.activate():
140 # Draw all the sprites.
141 self.tile_map.sprite_lists["Platforms"].draw()
142 self.player_list.draw()
143
144 with self.gui_camera.activate():
145 # Put the text on the screen.
146 # Adjust the text position based on the view port so that we don't
147 # scroll the text too.
148 output = f"FPS: {1/self.window.delta_time:.0f}"
149 arcade.draw_text(
150 output, 10, 20, arcade.color.BLACK, 14
151 )
152
153 if self.game_over:
154 self.game_over_text.position = self.window.center
155 self.game_over_text.draw()
156
157 def on_key_press(self, key, modifiers):
158 """
159 Called whenever the mouse moves.
160 """
161 if key == arcade.key.UP:
162 if self.physics_engine.can_jump():
163 self.player_sprite.change_y = JUMP_SPEED
164 elif key == arcade.key.LEFT:
165 self.player_sprite.change_x = -MOVEMENT_SPEED
166 elif key == arcade.key.RIGHT:
167 self.player_sprite.change_x = MOVEMENT_SPEED
168
169 def on_key_release(self, key, modifiers):
170 """
171 Called when the user presses a mouse button.
172 """
173 if key == arcade.key.LEFT or key == arcade.key.RIGHT:
174 self.player_sprite.change_x = 0
175
176 def on_update(self, delta_time):
177 """Movement and game logic"""
178
179 if self.player_sprite.right >= self.end_of_map:
180 if self.level < self.max_level:
181 self.level += 1
182 self.load_level(self.level)
183 self.player_sprite.center_x = 128
184 self.player_sprite.center_y = 64
185 self.player_sprite.change_x = 0
186 self.player_sprite.change_y = 0
187 else:
188 self.game_over = True
189
190 # Call update on all sprites (The sprites don't do much in this
191 # example though.)
192 if not self.game_over:
193 self.physics_engine.update()
194
195 # --- Manage Scrolling ---
196 self.game_camera.position = arcade.math.smerp_2d(
197 self.game_camera.position,
198 self.player_sprite.position,
199 delta_time,
200 CAMERA_PAN_SPEED
201 )
202 self.game_camera.position = arcade.camera.grips.constrain_xy(
203 self.game_camera.view_data,
204 self.camera_bounds
205 )
206
207
208def main():
209 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
210 game = GameView()
211 game.setup()
212
213 window.show_view(game)
214 window.run()
215
216
217if __name__ == "__main__":
218 main()