Load a TMX Map

Screenshot of using a larger map created by the Tiled Map Editor
platform_tutorial/08_load_map.py
  1"""
  2Platformer Game
  3"""
  4import arcade
  5
  6# Constants
  7SCREEN_WIDTH = 1000
  8SCREEN_HEIGHT = 650
  9SCREEN_TITLE = "Platformer"
 10
 11# Constants used to scale our sprites from their original size
 12CHARACTER_SCALING = 1
 13TILE_SCALING = 0.5
 14COIN_SCALING = 0.5
 15SPRITE_PIXEL_SIZE = 128
 16GRID_PIXEL_SIZE = (SPRITE_PIXEL_SIZE * TILE_SCALING)
 17
 18# Movement speed of player, in pixels per frame
 19PLAYER_MOVEMENT_SPEED = 10
 20GRAVITY = 1
 21PLAYER_JUMP_SPEED = 20
 22
 23# How many pixels to keep as a minimum margin between the character
 24# and the edge of the screen.
 25LEFT_VIEWPORT_MARGIN = 250
 26RIGHT_VIEWPORT_MARGIN = 250
 27BOTTOM_VIEWPORT_MARGIN = 100
 28TOP_VIEWPORT_MARGIN = 100
 29
 30
 31class MyGame(arcade.Window):
 32    """
 33    Main application class.
 34    """
 35
 36    def __init__(self):
 37
 38        # Call the parent class and set up the window
 39        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 40
 41        # These are 'lists' that keep track of our sprites. Each sprite should
 42        # go into a list.
 43        self.coin_list = None
 44        self.wall_list = None
 45        self.player_list = None
 46
 47        # Separate variable that holds the player sprite
 48        self.player_sprite = None
 49
 50        # Our physics engine
 51        self.physics_engine = None
 52
 53        # Used to keep track of our scrolling
 54        self.view_bottom = 0
 55        self.view_left = 0
 56
 57        # Keep track of the score
 58        self.score = 0
 59
 60        # Load sounds
 61        self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
 62        self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
 63
 64        arcade.set_background_color(arcade.csscolor.CORNFLOWER_BLUE)
 65
 66    def setup(self):
 67        """ Set up the game here. Call this function to restart the game. """
 68
 69        # Used to keep track of our scrolling
 70        self.view_bottom = 0
 71        self.view_left = 0
 72
 73        # Keep track of the score
 74        self.score = 0
 75
 76        # Create the Sprite lists
 77        self.player_list = arcade.SpriteList()
 78        self.wall_list = arcade.SpriteList()
 79        self.coin_list = arcade.SpriteList()
 80
 81        # Set up the player, specifically placing it at these coordinates.
 82        image_source = ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
 83        self.player_sprite = arcade.Sprite(image_source, CHARACTER_SCALING)
 84        self.player_sprite.center_x = 128
 85        self.player_sprite.center_y = 128
 86        self.player_list.append(self.player_sprite)
 87
 88        # --- Load in a map from the tiled editor ---
 89
 90        # Name of map file to load
 91        map_name = ":resources:tmx_maps/map.tmx"
 92        # Name of the layer in the file that has our platforms/walls
 93        platforms_layer_name = 'Platforms'
 94        # Name of the layer that has items for pick-up
 95        coins_layer_name = 'Coins'
 96
 97        # Read in the tiled map
 98        my_map = arcade.tilemap.read_tmx(map_name)
 99
100        # -- Platforms
101        self.wall_list = arcade.tilemap.process_layer(map_object=my_map,
102                                                      layer_name=platforms_layer_name,
103                                                      scaling=TILE_SCALING,
104                                                      use_spatial_hash=True)
105
106        # -- Coins
107        self.coin_list = arcade.tilemap.process_layer(my_map, coins_layer_name, TILE_SCALING)
108
109        # --- Other stuff
110        # Set the background color
111        if my_map.background_color:
112            arcade.set_background_color(my_map.background_color)
113
114        # Create the 'physics engine'
115        self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite,
116                                                             self.wall_list,
117                                                             GRAVITY)
118
119    def on_draw(self):
120        """ Render the screen. """
121
122        # Clear the screen to the background color
123        arcade.start_render()
124
125        # Draw our sprites
126        self.wall_list.draw()
127        self.coin_list.draw()
128        self.player_list.draw()
129
130        # Draw our score on the screen, scrolling it with the viewport
131        score_text = f"Score: {self.score}"
132        arcade.draw_text(score_text, 10 + self.view_left, 10 + self.view_bottom,
133                         arcade.csscolor.WHITE, 18)
134
135    def on_key_press(self, key, modifiers):
136        """Called whenever a key is pressed. """
137
138        if key == arcade.key.UP or key == arcade.key.W:
139            if self.physics_engine.can_jump():
140                self.player_sprite.change_y = PLAYER_JUMP_SPEED
141                arcade.play_sound(self.jump_sound)
142        elif key == arcade.key.LEFT or key == arcade.key.A:
143            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
144        elif key == arcade.key.RIGHT or key == arcade.key.D:
145            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
146
147    def on_key_release(self, key, modifiers):
148        """Called when the user releases a key. """
149
150        if key == arcade.key.LEFT or key == arcade.key.A:
151            self.player_sprite.change_x = 0
152        elif key == arcade.key.RIGHT or key == arcade.key.D:
153            self.player_sprite.change_x = 0
154
155    def on_update(self, delta_time):
156        """ Movement and game logic """
157
158        # Move the player with the physics engine
159        self.physics_engine.update()
160
161        # See if we hit any coins
162        coin_hit_list = arcade.check_for_collision_with_list(self.player_sprite,
163                                                             self.coin_list)
164
165        # Loop through each coin we hit (if any) and remove it
166        for coin in coin_hit_list:
167            # Remove the coin
168            coin.remove_from_sprite_lists()
169            # Play a sound
170            arcade.play_sound(self.collect_coin_sound)
171            # Add one to the score
172            self.score += 1
173
174        # --- Manage Scrolling ---
175
176        # Track if we need to change the viewport
177
178        changed = False
179
180        # Scroll left
181        left_boundary = self.view_left + LEFT_VIEWPORT_MARGIN
182        if self.player_sprite.left < left_boundary:
183            self.view_left -= left_boundary - self.player_sprite.left
184            changed = True
185
186        # Scroll right
187        right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_VIEWPORT_MARGIN
188        if self.player_sprite.right > right_boundary:
189            self.view_left += self.player_sprite.right - right_boundary
190            changed = True
191
192        # Scroll up
193        top_boundary = self.view_bottom + SCREEN_HEIGHT - TOP_VIEWPORT_MARGIN
194        if self.player_sprite.top > top_boundary:
195            self.view_bottom += self.player_sprite.top - top_boundary
196            changed = True
197
198        # Scroll down
199        bottom_boundary = self.view_bottom + BOTTOM_VIEWPORT_MARGIN
200        if self.player_sprite.bottom < bottom_boundary:
201            self.view_bottom -= bottom_boundary - self.player_sprite.bottom
202            changed = True
203
204        if changed:
205            # Only scroll to integers. Otherwise we end up with pixels that
206            # don't line up on the screen
207            self.view_bottom = int(self.view_bottom)
208            self.view_left = int(self.view_left)
209
210            # Do the scrolling
211            arcade.set_viewport(self.view_left,
212                                SCREEN_WIDTH + self.view_left,
213                                self.view_bottom,
214                                SCREEN_HEIGHT + self.view_bottom)
215
216
217def main():
218    """ Main method """
219    window = MyGame()
220    window.setup()
221    arcade.run()
222
223
224if __name__ == "__main__":
225    main()