使用级别和切片地图#

使用切片地图编辑器创建的较大地图的屏幕截图
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_MARGIN_RIGHT = 270
 28VIEWPORT_MARGIN_LEFT = 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.cam = None
 57        self.end_of_map = 0
 58        self.game_over = False
 59        self.last_time = None
 60        self.frame_count = 0
 61        self.fps_message = None
 62
 63        self.level = 1
 64        self.max_level = 2
 65
 66    def setup(self):
 67        """Set up the game and initialize the variables."""
 68
 69        # Sprite lists
 70        self.player_list = arcade.SpriteList()
 71
 72        # Set up the player
 73        self.player_sprite = arcade.Sprite(
 74            ":resources:images/animated_characters/female_person/femalePerson_idle.png",
 75            scale=PLAYER_SCALING,
 76        )
 77
 78        # Starting position of the player
 79        self.player_sprite.center_x = 128
 80        self.player_sprite.center_y = 64
 81        self.player_list.append(self.player_sprite)
 82
 83        self.load_level(self.level)
 84
 85        self.game_over = False
 86
 87    def load_level(self, level):
 88        # layer_options = {"Platforms": {"use_spatial_hash": True}}
 89
 90        # Read in the tiled map
 91        self.tile_map = arcade.load_tilemap(
 92            f":resources:tiled_maps/level_{level}.json", scaling=TILE_SPRITE_SCALING
 93        )
 94
 95        # --- Walls ---
 96
 97        # Calculate the right edge of the my_map in pixels
 98        self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE
 99
100        self.physics_engine = arcade.PhysicsEnginePlatformer(
101            self.player_sprite,
102            self.tile_map.sprite_lists["Platforms"],
103            gravity_constant=GRAVITY,
104        )
105
106        # --- Other stuff
107        # Set the background color
108        if self.tile_map.background_color:
109            self.background_color = self.tile_map.background_color
110
111        # Reset cam
112        self.cam = arcade.camera.Camera2D()
113
114    def on_draw(self):
115        """
116        Render the screen.
117        """
118
119        self.frame_count += 1
120
121        # This command has to happen before we start drawing
122        self.clear()
123
124        # Draw all the sprites.
125        self.player_list.draw()
126        self.tile_map.sprite_lists["Platforms"].draw()
127
128        if self.last_time and self.frame_count % 60 == 0:
129            fps = 1.0 / (time.time() - self.last_time) * 60
130            self.fps_message = f"FPS: {fps:5.0f}"
131
132        if self.fps_message:
133            arcade.draw_text(
134                self.fps_message,
135                self.cam.left + 10,
136                self.cam.bottom + 40,
137                arcade.color.BLACK,
138                14,
139            )
140
141        if self.frame_count % 60 == 0:
142            self.last_time = time.time()
143
144        # Put the text on the screen.
145        # Adjust the text position based on the view port so that we don't
146        # scroll the text too.
147        distance = self.player_sprite.right
148        output = f"Distance: {distance:.0f}"
149        arcade.draw_text(
150            output, self.cam.left + 10, self.cam.bottom + 20, arcade.color.BLACK, 14
151        )
152
153        if self.game_over:
154            arcade.draw_text(
155                "Game Over",
156                self.cam.left + 200,
157                self.cam.bottom + 200,
158                arcade.color.BLACK,
159                30,
160            )
161
162    def on_key_press(self, key, modifiers):
163        """
164        Called whenever the mouse moves.
165        """
166        if key == arcade.key.UP:
167            if self.physics_engine.can_jump():
168                self.player_sprite.change_y = JUMP_SPEED
169        elif key == arcade.key.LEFT:
170            self.player_sprite.change_x = -MOVEMENT_SPEED
171        elif key == arcade.key.RIGHT:
172            self.player_sprite.change_x = MOVEMENT_SPEED
173
174    def on_key_release(self, key, modifiers):
175        """
176        Called when the user presses a mouse button.
177        """
178        if key == arcade.key.LEFT or key == arcade.key.RIGHT:
179            self.player_sprite.change_x = 0
180
181    def on_update(self, delta_time):
182        """Movement and game logic"""
183
184        if self.player_sprite.right >= self.end_of_map:
185            if self.level < self.max_level:
186                self.level += 1
187                self.load_level(self.level)
188                self.player_sprite.center_x = 128
189                self.player_sprite.center_y = 64
190                self.player_sprite.change_x = 0
191                self.player_sprite.change_y = 0
192            else:
193                self.game_over = True
194
195        # Call update on all sprites (The sprites don't do much in this
196        # example though.)
197        if not self.game_over:
198            self.physics_engine.update()
199
200        # --- Manage Scrolling ---
201
202        # Track if we need to change the viewport
203
204        changed = False
205
206        # Scroll left
207        left_bndry = self.cam.left + VIEWPORT_MARGIN_LEFT
208        if self.player_sprite.left < left_bndry:
209            self.cam.left -= left_bndry - self.player_sprite.left
210            changed = True
211
212        # Scroll right
213        right_bndry = self.cam.right - VIEWPORT_MARGIN_RIGHT
214        if self.player_sprite.right > right_bndry:
215            self.cam.left += self.player_sprite.right - right_bndry
216            changed = True
217
218        # Scroll up
219        top_bndry = self.cam.top - VIEWPORT_MARGIN_TOP
220        if self.player_sprite.top > top_bndry:
221            self.cam.bottom += self.player_sprite.top - top_bndry
222            changed = True
223
224        # Scroll down
225        bottom_bndry = self.cam.bottom + VIEWPORT_MARGIN_BOTTOM
226        if self.player_sprite.bottom < bottom_bndry:
227            self.cam.bottom -= bottom_bndry - self.player_sprite.bottom
228            changed = True
229
230        if changed:
231            self.cam.use()
232
233
234def main():
235    window = MyGame()
236    window.setup()
237    arcade.run()
238
239
240if __name__ == "__main__":
241    main()