第13步-更多类型的层#

对于这个例子,我们将切换到一个不同的内置地图,它有更多的层可以用来做事情。

在我们的设置功能中,加载此地图,而不是第12章中的地图:

self.tile_map = arcade.load_tilemap(":resources:tiled_maps/map2_level_1.json", scaling=TILE_SCALING, layer_options=layer_options)

您可以运行此程序并查看我们将在本章中使用的地图。你会注意到,除了我们已经拥有的正常平台和硬币之外。我们现在有了一些额外的标志和装饰物品,以及一个熔岩坑。

回到第6章,我们利用我们的 setup 重置游戏的功能。让我们继续使用这个系统,当玩家接触到熔岩坑时,重新设置游戏。如果需要,您可以在按Esc键时删除用于重置的部分,也可以将其保留在原处。当这种情况发生时,我们也可以通过声音玩游戏。

让我们首先为我们的 __init__ 函数用于以下操作:

self.gameover_sound = arcade.load_sound(":resources:sounds/gameover1.wav")

为了做到这一点,我们将在我们的 on_update 功能:

if arcade.check_for_collision_with_list(
    self.player_sprite, self.scene["Don't Touch"]
):
    arcade.play_sound(self.gameover_sound)
    self.setup()

我们在这里使用的地图中有一些额外的层,我们还没有使用过。在上面的代码中,我们使用 Don't Touch 在玩家触摸游戏时重置游戏。在这一部分中,我们将使用新地图中的另外两个图层, BackgroundForeground

我们将使用这些层来区分应该在玩家面前绘制的对象和应该在玩家后面绘制的对象。在我们的 setup 函数,在我们创建PlayerSprite之前,添加以下代码。

self.scene.add_sprite_list_after("Player", "Foreground")

这段代码将使我们的玩家精灵列表被插入到场景中的特定位置。使它前面的精灵画在它前面,后面的精灵画在后面。通过这样做,我们可以使对象出现在玩家的前面或后面,如下图所示:

../../_images/13_foreground.png ../../_images/13_background.png

源代码#

更多层#
  1"""
  2Platformer Game
  3
  4python -m arcade.examples.platform_tutorial.13_more_layers
  5"""
  6import arcade
  7
  8# Constants
  9SCREEN_WIDTH = 800
 10SCREEN_HEIGHT = 600
 11SCREEN_TITLE = "Platformer"
 12
 13# Constants used to scale our sprites from their original size
 14TILE_SCALING = 0.5
 15COIN_SCALING = 0.5
 16
 17# Movement speed of player, in pixels per frame
 18PLAYER_MOVEMENT_SPEED = 5
 19GRAVITY = 1
 20PLAYER_JUMP_SPEED = 20
 21
 22
 23class MyGame(arcade.Window):
 24    """
 25    Main application class.
 26    """
 27
 28    def __init__(self):
 29
 30        # Call the parent class and set up the window
 31        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 32
 33        # Variable to hold our texture for our player
 34        self.player_texture = None
 35
 36        # Separate variable that holds the player sprite
 37        self.player_sprite = None
 38
 39        # Variable to hold our Tiled Map
 40        self.tile_map = None
 41
 42        # Replacing all of our SpriteLists with a Scene variable
 43        self.scene = None
 44
 45        # A variable to store our camera object
 46        self.camera = None
 47
 48        # A variable to store our gui camera object
 49        self.gui_camera = None
 50
 51        # This variable will store our score as an integer.
 52        self.score = 0
 53
 54        # This variable will store the text for score that we will draw to the screen.
 55        self.score_text = None
 56
 57        # Load sounds
 58        self.collect_coin_sound = arcade.load_sound(":resources:sounds/coin1.wav")
 59        self.jump_sound = arcade.load_sound(":resources:sounds/jump1.wav")
 60        self.gameover_sound = arcade.load_sound(":resources:sounds/gameover1.wav")
 61
 62    def setup(self):
 63        """Set up the game here. Call this function to restart the game."""
 64        layer_options = {
 65            "Platforms": {
 66                "use_spatial_hash": True
 67            }
 68        }
 69
 70        # Load our TileMap
 71        self.tile_map = arcade.load_tilemap(":resources:tiled_maps/map2_level_1.json", scaling=TILE_SCALING, layer_options=layer_options)
 72
 73        # Create our Scene Based on the TileMap
 74        self.scene = arcade.Scene.from_tilemap(self.tile_map)
 75
 76        self.player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
 77
 78        # Add Player Spritelist before "Foreground" layer. This will make the foreground
 79        # be drawn after the player, making it appear to be in front of the Player.
 80        # Setting before using scene.add_sprite allows us to define where the SpriteList
 81        # will be in the draw order. If we just use add_sprite, it will be appended to the
 82        # end of the order.
 83        self.scene.add_sprite_list_after("Player", "Foreground")
 84
 85        self.player_sprite = arcade.Sprite(self.player_texture)
 86        self.player_sprite.center_x = 128
 87        self.player_sprite.center_y = 128
 88        self.scene.add_sprite("Player", self.player_sprite)
 89
 90        # Create a Platformer Physics Engine, this will handle moving our
 91        # player as well as collisions between the player sprite and
 92        # whatever SpriteList we specify for the walls.
 93        # It is important to supply static to the walls parameter. There is a
 94        # platforms parameter that is intended for moving platforms.
 95        # If a platform is supposed to move, and is added to the walls list,
 96        # it will not be moved.
 97        self.physics_engine = arcade.PhysicsEnginePlatformer(
 98            self.player_sprite, walls=self.scene["Platforms"], gravity_constant=GRAVITY
 99        )
100
101        # Initialize our camera, setting a viewport the size of our window.
102        self.camera = arcade.camera.Camera2D()
103
104        # Initialize our gui camera, initial settings are the same as our world camera.
105        self.gui_camera = arcade.camera.Camera2D()
106
107        # Reset our score to 0
108        self.score = 0
109
110        # Initialize our arcade.Text object for score
111        self.score_text = arcade.Text(f"Score: {self.score}", x=0, y=5)
112
113        self.background_color = arcade.csscolor.CORNFLOWER_BLUE
114
115    def on_draw(self):
116        """Render the screen."""
117
118        # Clear the screen to the background color
119        self.clear()
120
121        # Activate our camera before drawing
122        self.camera.use()
123
124        # Draw our Scene
125        self.scene.draw()
126
127        # Activate our GUI camera
128        self.gui_camera.use()
129
130        # Draw our Score
131        self.score_text.draw()
132
133    def on_update(self, delta_time):
134        """Movement and Game Logic"""
135
136        # Move the player using our physics engine
137        self.physics_engine.update()
138
139        # See if we hit any coins
140        coin_hit_list = arcade.check_for_collision_with_list(
141            self.player_sprite, self.scene["Coins"]
142        )
143
144        # Loop through each coin we hit (if any) and remove it
145        for coin in coin_hit_list:
146            # Remove the coin
147            coin.remove_from_sprite_lists()
148            arcade.play_sound(self.collect_coin_sound)
149            self.score += 75
150            self.score_text.text = f"Score: {self.score}"
151
152        if arcade.check_for_collision_with_list(
153            self.player_sprite, self.scene["Don't Touch"]
154        ):
155            arcade.play_sound(self.gameover_sound)
156            self.setup()
157
158        # Center our camera on the player
159        self.camera.position = self.player_sprite.position
160
161    def on_key_press(self, key, modifiers):
162        """Called whenever a key is pressed."""
163
164        if key == arcade.key.ESCAPE:
165            self.setup()
166
167        if key == arcade.key.UP or key == arcade.key.W:
168            if self.physics_engine.can_jump():
169                self.player_sprite.change_y = PLAYER_JUMP_SPEED
170                arcade.play_sound(self.jump_sound)
171
172        if key == arcade.key.LEFT or key == arcade.key.A:
173            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
174        elif key == arcade.key.RIGHT or key == arcade.key.D:
175            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
176
177    def on_key_release(self, key, modifiers):
178        """Called whenever a key is released."""
179
180        if key == arcade.key.LEFT or key == arcade.key.A:
181            self.player_sprite.change_x = 0
182        elif key == arcade.key.RIGHT or key == arcade.key.D:
183            self.player_sprite.change_x = 0
184
185
186def main():
187    """Main function"""
188    window = MyGame()
189    window.setup()
190    arcade.run()
191
192
193if __name__ == "__main__":
194    main()