第八步--收集硬币#

现在我们可以在比赛中完全移动了,我们需要给球员一个目标。电子游戏的一个经典目标是收集硬币,所以让我们继续添加这一点。

在这一章中,你将学习如何检查与我们的玩家的碰撞,并找出他们到底是什么碰撞,并对它做一些事情。现在我们只会在他们收集硬币的时候从屏幕上移除硬币,但在后面的章节中,我们会给角色一个分数,当他们收集硬币时,我们会增加分数。我们还将在稍后开始播放声音。

首先,我们将创建一个新的SpriteList来存放我们的硬币。就像我们的另一个墙精灵列表一样,继续向 __init__ 函数来存储它,然后在 setup 功能。目前,我们希望为此列表启用空间散列。如果你决定使用移动硬币,你会想要关掉它。

# Inside __init__
self.coin_list = None

# Inside setup
self.coin_list = arcade.SpriteList(use_spatial_hash=True)

看看你能不能用我们已经学到的东西把硬币添加到SpriteList中。为他们提供的内置资源是 :resources:images/items/coinGold.png 。提示:就像我们处理盒子和地面一样,你会想要缩放这些东西。如果你被卡住了,你可以查看下面的完整源代码,看看我们是如何按照我们在地面上使用的相同模式放置它们的。

一旦您放置了硬币并将它们添加到 coin_list ,不要忘记将它们添加到 on_draw

self.coin_list.draw()

现在我们正在将硬币画到屏幕上,我们如何让它们与玩家交互?当玩家击球时,我们希望将其从屏幕上移除。要做到这一点,我们将使用 arcade.check_for_collision_with_list() 功能。该函数接受一个Sprite,在本例中是我们的玩家,还有一个SpriteList,对于我们来说是硬币。它将返回一个列表,其中包含给定SpriteList中与Sprite发生冲突的所有Sprite。

我们可以使用for循环迭代该列表,以对发生冲突的每个精灵执行某些操作。这意味着,如果我们将多个硬币放在一起,我们可以检测到用户一次点击多个硬币。

为了做到这一点,并在玩家击中硬币精灵时将其移除,我们将把这个添加到 on_update 功能。

coin_hit_list = arcade.check_for_collision_with_list(
    self.player_sprite, self.coin_list
)

for coin in coin_hit_list:
    coin.remove_from_sprite_lists()

我们用这个 arcade.BasicSprite.remove_from_sprite_lists() 函数,以确保我们的Sprite从它所属的所有SpriteList中完全删除。

源代码#

收集硬币#
  1"""
  2Platformer Game
  3
  4python -m arcade.examples.platform_tutorial.08_coins
  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        # SpriteList for our player
 40        self.player_list = None
 41
 42        # SpriteList for our boxes and ground
 43        # Putting our ground and box Sprites in the same SpriteList
 44        # will make it easier to perform collision detection against
 45        # them later on. Setting the spatial hash to True will make
 46        # collision detection much faster if the objects in this
 47        # SpriteList do not move.
 48        self.wall_list = None
 49
 50        # SpriteList for coins the player can collect
 51        self.coin_list = None
 52
 53        # A variable to store our camera object
 54        self.camera = None
 55
 56    def setup(self):
 57        """Set up the game here. Call this function to restart the game."""
 58        self.player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
 59
 60        self.player_sprite = arcade.Sprite(self.player_texture)
 61        self.player_sprite.center_x = 64
 62        self.player_sprite.center_y = 128
 63
 64        self.player_list = arcade.SpriteList()
 65        self.player_list.append(self.player_sprite)
 66
 67        self.wall_list = arcade.SpriteList(use_spatial_hash=True)
 68        self.coin_list = arcade.SpriteList(use_spatial_hash=True)
 69
 70        # Create the ground
 71        # This shows using a loop to place multiple sprites horizontally
 72        for x in range(0, 1250, 64):
 73            wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
 74            wall.center_x = x
 75            wall.center_y = 32
 76            self.wall_list.append(wall)
 77
 78        # Put some crates on the ground
 79        # This shows using a coordinate list to place sprites
 80        coordinate_list = [[512, 96], [256, 96], [768, 96]]
 81
 82        for coordinate in coordinate_list:
 83            # Add a crate on the ground
 84            wall = arcade.Sprite(
 85                ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
 86            )
 87            wall.position = coordinate
 88            self.wall_list.append(wall)
 89
 90        # Add coins to the world
 91        for x in range(128, 1250, 256):
 92            coin = arcade.Sprite(":resources:images/items/coinGold.png", scale=COIN_SCALING)
 93            coin.center_x = x
 94            coin.center_y = 96
 95            self.coin_list.append(coin)
 96
 97        # Create a Platformer Physics Engine, this will handle moving our
 98        # player as well as collisions between the player sprite and
 99        # whatever SpriteList we specify for the walls.
100        # It is important to supply static to the walls parameter. There is a
101        # platforms parameter that is intended for moving platforms.
102        # If a platform is supposed to move, and is added to the walls list,
103        # it will not be moved.
104        self.physics_engine = arcade.PhysicsEnginePlatformer(
105            self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
106        )
107
108        # Initialize our camera, setting a viewport the size of our window.
109        self.camera = arcade.camera.Camera2D()
110
111        self.background_color = arcade.csscolor.CORNFLOWER_BLUE
112
113    def on_draw(self):
114        """Render the screen."""
115
116        # Clear the screen to the background color
117        self.clear()
118
119        # Activate our camera before drawing
120        self.camera.use()
121
122        # Draw our sprites
123        self.player_list.draw()
124        self.wall_list.draw()
125        self.coin_list.draw()
126
127    def on_update(self, delta_time):
128        """Movement and Game Logic"""
129
130        # Move the player using our physics engine
131        self.physics_engine.update()
132
133        # See if we hit any coins
134        coin_hit_list = arcade.check_for_collision_with_list(
135            self.player_sprite, self.coin_list
136        )
137
138        # Loop through each coin we hit (if any) and remove it
139        for coin in coin_hit_list:
140            # Remove the coin
141            coin.remove_from_sprite_lists()
142
143        # Center our camera on the player
144        self.camera.position = self.player_sprite.position
145
146    def on_key_press(self, key, modifiers):
147        """Called whenever a key is pressed."""
148
149        if key == arcade.key.ESCAPE:
150            self.setup()
151
152        if key == arcade.key.UP or key == arcade.key.W:
153            if self.physics_engine.can_jump():
154                self.player_sprite.change_y = PLAYER_JUMP_SPEED
155
156        if key == arcade.key.LEFT or key == arcade.key.A:
157            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
158        elif key == arcade.key.RIGHT or key == arcade.key.D:
159            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
160
161    def on_key_release(self, key, modifiers):
162        """Called whenever a key is released."""
163
164        if key == arcade.key.LEFT or key == arcade.key.A:
165            self.player_sprite.change_x = 0
166        elif key == arcade.key.RIGHT or key == arcade.key.D:
167            self.player_sprite.change_x = 0
168
169
170def main():
171    """Main function"""
172    window = MyGame()
173    window.setup()
174    arcade.run()
175
176
177if __name__ == "__main__":
178    main()

运行本章#

python -m arcade.examples.platform_tutorial.08_coins