第11步-添加梯子、属性和移动平台#

此示例显示了如何使用:
梯子
用于定义硬币和旗帜点值的属性
属性和对象层来定义移动平台。
要使用TMX编辑器创建移动平台,有几个步骤:
定义一个 对象层 而不是瓷砖层。
选择 插入平铺
选择要插入的磁贴。
放置瓷砖。
添加自定义属性。您可以添加:
change_x
change_y
boundary_bottom
boundary_top
boundary_left
boundary_right

梯子、动画瓷砖和移动平台#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | """ Platformer Game """ import os import arcade # Constants SCREEN_WIDTH = 1000 SCREEN_HEIGHT = 650 SCREEN_TITLE = "Platformer" # Constants used to scale our sprites from their original size CHARACTER_SCALING = 1 TILE_SCALING = 0.5 COIN_SCALING = 0.5 SPRITE_PIXEL_SIZE = 128 GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SCALING # Movement speed of player, in pixels per frame PLAYER_MOVEMENT_SPEED = 7 GRAVITY = 1.5 PLAYER_JUMP_SPEED = 30 PLAYER_START_X = 64 PLAYER_START_Y = 256 # Layer Names from our TileMap LAYER_NAME_MOVING_PLATFORMS = "Moving Platforms" LAYER_NAME_PLATFORMS = "Platforms" LAYER_NAME_COINS = "Coins" LAYER_NAME_BACKGROUND = "Background" LAYER_NAME_LADDERS = "Ladders" class MyGame(arcade.Window): """ Main application class. """ def __init__(self): """ Initializer for the game """ # Call the parent class and set up the window super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) # Set the path to start with this program file_path = os.path.dirname(os.path.abspath(__file__)) os.chdir(file_path) # Our TileMap Object self.tile_map = None # Our Scene Object self.scene = None # Separate variable that holds the player sprite self.player_sprite = None # Our 'physics' engine self.physics_engine = None # A Camera that can be used for scrolling the screen self.camera = None # A Camera that can be used to draw GUI elements self.gui_camera = None self.end_of_map = 0 # Keep track of the score self.score = 0 # Load sounds self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav") self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav") self.game_over = arcade.load_sound(":resources:sounds/gameover1.wav") def setup(self): """Set up the game here. Call this function to restart the game.""" # Set up the Cameras self.camera = arcade.Camera(self.width, self.height) self.gui_camera = arcade.Camera(self.width, self.height) # Map name map_name = ":resources:tiled_maps/map_with_ladders.json" # Layer Specific Options for the Tilemap layer_options = { LAYER_NAME_PLATFORMS: { "use_spatial_hash": True, }, LAYER_NAME_MOVING_PLATFORMS: { "use_spatial_hash": False, }, LAYER_NAME_LADDERS: { "use_spatial_hash": True, }, LAYER_NAME_COINS: { "use_spatial_hash": True, }, } # Load in TileMap self.tile_map = arcade.load_tilemap(map_name, TILE_SCALING, layer_options) # Initiate New Scene with our TileMap, this will automatically add all layers # from the map as SpriteLists in the scene in the proper order. self.scene = arcade.Scene.from_tilemap(self.tile_map) # Keep track of the score self.score = 0 # Set up the player, specifically placing it at these coordinates. image_source = ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png" self.player_sprite = arcade.Sprite(image_source, CHARACTER_SCALING) self.player_sprite.center_x = PLAYER_START_X self.player_sprite.center_y = PLAYER_START_Y self.scene.add_sprite("Player", self.player_sprite) # Calculate the right edge of the my_map in pixels self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE # --- Other stuff # Set the background color if self.tile_map.background_color: arcade.set_background_color(self.tile_map.background_color) # Create the 'physics engine' self.physics_engine = arcade.PhysicsEnginePlatformer( self.player_sprite, platforms=self.scene[LAYER_NAME_MOVING_PLATFORMS], gravity_constant=GRAVITY, ladders=self.scene[LAYER_NAME_LADDERS], walls=self.scene[LAYER_NAME_PLATFORMS] ) def on_draw(self): """Render the screen.""" # Clear the screen to the background color self.clear() # Activate the game camera self.camera.use() # Draw our Scene self.scene.draw() # Activate the GUI camera before drawing GUI elements self.gui_camera.use() # Draw our score on the screen, scrolling it with the viewport score_text = f"Score: {self.score}" arcade.draw_text( score_text, 10, 10, arcade.csscolor.BLACK, 18, ) def on_key_press(self, key, modifiers): """Called whenever a key is pressed.""" if key == arcade.key.UP or key == arcade.key.W: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = PLAYER_MOVEMENT_SPEED elif self.physics_engine.can_jump(): self.player_sprite.change_y = PLAYER_JUMP_SPEED arcade.play_sound(self.jump_sound) elif key == arcade.key.DOWN or key == arcade.key.S: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = -PLAYER_MOVEMENT_SPEED elif key == arcade.key.LEFT or key == arcade.key.A: self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED elif key == arcade.key.RIGHT or key == arcade.key.D: self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED def on_key_release(self, key, modifiers): """Called when the user releases a key.""" if key == arcade.key.UP or key == arcade.key.W: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = 0 elif key == arcade.key.DOWN or key == arcade.key.S: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = 0 elif key == arcade.key.LEFT or key == arcade.key.A: self.player_sprite.change_x = 0 elif key == arcade.key.RIGHT or key == arcade.key.D: self.player_sprite.change_x = 0 def center_camera_to_player(self): screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2) screen_center_y = self.player_sprite.center_y - ( self.camera.viewport_height / 2 ) if screen_center_x < 0: screen_center_x = 0 if screen_center_y < 0: screen_center_y = 0 player_centered = screen_center_x, screen_center_y self.camera.move_to(player_centered, 0.2) def update(self, delta_time): """Movement and game logic""" # Move the player with the physics engine self.physics_engine.update() # Update animations self.scene.update_animation( delta_time, [LAYER_NAME_COINS, LAYER_NAME_BACKGROUND] ) # Update walls, used with moving platforms self.scene.update([LAYER_NAME_MOVING_PLATFORMS]) # See if we hit any coins coin_hit_list = arcade.check_for_collision_with_list( self.player_sprite, self.scene[LAYER_NAME_COINS] ) # Loop through each coin we hit (if any) and remove it for coin in coin_hit_list: # Figure out how many points this coin is worth if "Points" not in coin.properties: print("Warning, collected a coin without a Points property.") else: points = int(coin.properties["Points"]) self.score += points # Remove the coin coin.remove_from_sprite_lists() arcade.play_sound(self.collect_coin_sound) # Position the camera self.center_camera_to_player() def main(): """Main function""" window = MyGame() window.setup() arcade.run() if __name__ == "__main__": main() |
源代码#
梯子和更多#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | """ Platformer Game """ import os import arcade # Constants SCREEN_WIDTH = 1000 SCREEN_HEIGHT = 650 SCREEN_TITLE = "Platformer" # Constants used to scale our sprites from their original size CHARACTER_SCALING = 1 TILE_SCALING = 0.5 COIN_SCALING = 0.5 SPRITE_PIXEL_SIZE = 128 GRID_PIXEL_SIZE = SPRITE_PIXEL_SIZE * TILE_SCALING # Movement speed of player, in pixels per frame PLAYER_MOVEMENT_SPEED = 7 GRAVITY = 1.5 PLAYER_JUMP_SPEED = 30 PLAYER_START_X = 64 PLAYER_START_Y = 256 # Layer Names from our TileMap LAYER_NAME_MOVING_PLATFORMS = "Moving Platforms" LAYER_NAME_PLATFORMS = "Platforms" LAYER_NAME_COINS = "Coins" LAYER_NAME_BACKGROUND = "Background" LAYER_NAME_LADDERS = "Ladders" class MyGame(arcade.Window): """ Main application class. """ def __init__(self): """ Initializer for the game """ # Call the parent class and set up the window super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) # Set the path to start with this program file_path = os.path.dirname(os.path.abspath(__file__)) os.chdir(file_path) # Our TileMap Object self.tile_map = None # Our Scene Object self.scene = None # Separate variable that holds the player sprite self.player_sprite = None # Our 'physics' engine self.physics_engine = None # A Camera that can be used for scrolling the screen self.camera = None # A Camera that can be used to draw GUI elements self.gui_camera = None self.end_of_map = 0 # Keep track of the score self.score = 0 # Load sounds self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav") self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav") self.game_over = arcade.load_sound(":resources:sounds/gameover1.wav") def setup(self): """Set up the game here. Call this function to restart the game.""" # Set up the Cameras self.camera = arcade.Camera(self.width, self.height) self.gui_camera = arcade.Camera(self.width, self.height) # Map name map_name = ":resources:tiled_maps/map_with_ladders.json" # Layer Specific Options for the Tilemap layer_options = { LAYER_NAME_PLATFORMS: { "use_spatial_hash": True, }, LAYER_NAME_MOVING_PLATFORMS: { "use_spatial_hash": False, }, LAYER_NAME_LADDERS: { "use_spatial_hash": True, }, LAYER_NAME_COINS: { "use_spatial_hash": True, }, } # Load in TileMap self.tile_map = arcade.load_tilemap(map_name, TILE_SCALING, layer_options) # Initiate New Scene with our TileMap, this will automatically add all layers # from the map as SpriteLists in the scene in the proper order. self.scene = arcade.Scene.from_tilemap(self.tile_map) # Keep track of the score self.score = 0 # Set up the player, specifically placing it at these coordinates. image_source = ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png" self.player_sprite = arcade.Sprite(image_source, CHARACTER_SCALING) self.player_sprite.center_x = PLAYER_START_X self.player_sprite.center_y = PLAYER_START_Y self.scene.add_sprite("Player", self.player_sprite) # Calculate the right edge of the my_map in pixels self.end_of_map = self.tile_map.width * GRID_PIXEL_SIZE # --- Other stuff # Set the background color if self.tile_map.background_color: arcade.set_background_color(self.tile_map.background_color) # Create the 'physics engine' self.physics_engine = arcade.PhysicsEnginePlatformer( self.player_sprite, platforms=self.scene[LAYER_NAME_MOVING_PLATFORMS], gravity_constant=GRAVITY, ladders=self.scene[LAYER_NAME_LADDERS], walls=self.scene[LAYER_NAME_PLATFORMS] ) def on_draw(self): """Render the screen.""" # Clear the screen to the background color self.clear() # Activate the game camera self.camera.use() # Draw our Scene self.scene.draw() # Activate the GUI camera before drawing GUI elements self.gui_camera.use() # Draw our score on the screen, scrolling it with the viewport score_text = f"Score: {self.score}" arcade.draw_text( score_text, 10, 10, arcade.csscolor.BLACK, 18, ) def on_key_press(self, key, modifiers): """Called whenever a key is pressed.""" if key == arcade.key.UP or key == arcade.key.W: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = PLAYER_MOVEMENT_SPEED elif self.physics_engine.can_jump(): self.player_sprite.change_y = PLAYER_JUMP_SPEED arcade.play_sound(self.jump_sound) elif key == arcade.key.DOWN or key == arcade.key.S: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = -PLAYER_MOVEMENT_SPEED elif key == arcade.key.LEFT or key == arcade.key.A: self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED elif key == arcade.key.RIGHT or key == arcade.key.D: self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED def on_key_release(self, key, modifiers): """Called when the user releases a key.""" if key == arcade.key.UP or key == arcade.key.W: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = 0 elif key == arcade.key.DOWN or key == arcade.key.S: if self.physics_engine.is_on_ladder(): self.player_sprite.change_y = 0 elif key == arcade.key.LEFT or key == arcade.key.A: self.player_sprite.change_x = 0 elif key == arcade.key.RIGHT or key == arcade.key.D: self.player_sprite.change_x = 0 def center_camera_to_player(self): screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2) screen_center_y = self.player_sprite.center_y - ( self.camera.viewport_height / 2 ) if screen_center_x < 0: screen_center_x = 0 if screen_center_y < 0: screen_center_y = 0 player_centered = screen_center_x, screen_center_y self.camera.move_to(player_centered, 0.2) def update(self, delta_time): """Movement and game logic""" # Move the player with the physics engine self.physics_engine.update() # Update animations self.scene.update_animation( delta_time, [LAYER_NAME_COINS, LAYER_NAME_BACKGROUND] ) # Update walls, used with moving platforms self.scene.update([LAYER_NAME_MOVING_PLATFORMS]) # See if we hit any coins coin_hit_list = arcade.check_for_collision_with_list( self.player_sprite, self.scene[LAYER_NAME_COINS] ) # Loop through each coin we hit (if any) and remove it for coin in coin_hit_list: # Figure out how many points this coin is worth if "Points" not in coin.properties: print("Warning, collected a coin without a Points property.") else: points = int(coin.properties["Points"]) self.score += points # Remove the coin coin.remove_from_sprite_lists() arcade.play_sound(self.collect_coin_sound) # Position the camera self.center_camera_to_player() def main(): """Main function""" window = MyGame() window.setup() arcade.run() if __name__ == "__main__": main() |