第5步-添加重力#

前面的例子对于自上而下的游戏来说是很棒的,但如果它是像我们的平台一样带有跳跃的侧视图呢?我们需要增加重力。首先,让我们定义一个常量来表示重力的加速度,一个常量来表示跳跃速度。

GRAVITY = 1
PLAYER_JUMP_SPEED = 20

现在,让我们更改我们在 __init__ 函数设置为 arcade.PhysicsEnginePlatformer 而不是一个 arcade.PhysicsEngineSimple 。这个新的物理引擎将为我们处理跳跃和重力,并将在后面的章节中做更多的工作。

self.physics_engine = arcade.PhysicsEnginePlatformer(
    self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
)

这与我们最初创建简单物理引擎的方式非常相似,但有两个例外。首先,我们给它发来了我们的重力常数。第二个原因是我们已将Wall SpriteList显式发送到 walls 参数。这是非常重要的一步。Platform物理引擎有两个用于可碰撞对象的参数,其中一个名为 platforms 和一个名为 walls

不同之处在于发送到 platforms 是用来移动的。它们的移动方式与玩家相同,通过修改它们的 change_xchange_y 价值观。对象发送到 walls 参数将不会移动。这一点如此重要的原因是,不动的墙比可移动的平台具有更快的性能。

通过添加静态精灵 platforms 参数大致是一个O(N)运算,这意味着随着您添加更多的精灵,性能将线性下降。如果将静态精灵添加到 walls 参数,那么它几乎是O(1),并且例如100个和50,000个不移动的精灵之间基本上没有区别。

最后,我们将给我们的球员跳跃的能力。修改 on_key_presson_key_release 功能。我们将删除以前的UP/DOWN语句,并使 UP 按下后跳跃。

if key == arcade.key.UP or key == arcade.key.W:
    if self.physics_engine.can_jump():
        self.player_sprite.change_y = PLAYER_JUMP_SPEED

这个 can_jump() 我们的物理引擎的检查将会成功,这样我们只有在接触地面时才能跳跃。您可以删除此功能,以允许跳到半空中以获得一些有趣的结果。想一想如何使用它来实现一个双跳系统。

备注

您可以通过更改重力和跳跃常量来更改用户的跳跃方式。两者的值越低,角色就越“漂浮”。值越高,游戏节奏越快。

源代码#

05_Add_gravity.py-添加重力#
  1"""
  2Platformer Game
  3
  4python -m arcade.examples.platform_tutorial.05_add_gravity
  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
 15
 16# Movement speed of player, in pixels per frame
 17PLAYER_MOVEMENT_SPEED = 5
 18GRAVITY = 1
 19PLAYER_JUMP_SPEED = 20
 20
 21
 22class MyGame(arcade.Window):
 23    """
 24    Main application class.
 25    """
 26
 27    def __init__(self):
 28
 29        # Call the parent class and set up the window
 30        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 31
 32        # Variable to hold our texture for our player
 33        self.player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
 34
 35        # Separate variable that holds the player sprite
 36        self.player_sprite = arcade.Sprite(self.player_texture)
 37        self.player_sprite.center_x = 64
 38        self.player_sprite.center_y = 128
 39
 40        # SpriteList for our player
 41        self.player_list = arcade.SpriteList()
 42        self.player_list.append(self.player_sprite)
 43
 44        # SpriteList for our boxes and ground
 45        # Putting our ground and box Sprites in the same SpriteList
 46        # will make it easier to perform collision detection against
 47        # them later on. Setting the spatial hash to True will make
 48        # collision detection much faster if the objects in this
 49        # SpriteList do not move.
 50        self.wall_list = arcade.SpriteList(use_spatial_hash=True)
 51
 52        # Create the ground
 53        # This shows using a loop to place multiple sprites horizontally
 54        for x in range(0, 1250, 64):
 55            wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
 56            wall.center_x = x
 57            wall.center_y = 32
 58            self.wall_list.append(wall)
 59
 60        # Put some crates on the ground
 61        # This shows using a coordinate list to place sprites
 62        coordinate_list = [[512, 96], [256, 96], [768, 96]]
 63
 64        for coordinate in coordinate_list:
 65            # Add a crate on the ground
 66            wall = arcade.Sprite(
 67                ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
 68            )
 69            wall.position = coordinate
 70            self.wall_list.append(wall)
 71
 72        # Create a Platformer Physics Engine. 
 73        # This will handle moving our player as well as collisions between 
 74        # the player sprite and whatever SpriteList we specify for the walls.
 75        # It is important to supply static platforms to the walls parameter. There is a
 76        # platforms parameter that is intended for moving platforms.
 77        # If a platform is supposed to move, and is added to the walls list,
 78        # it will not be moved.
 79        self.physics_engine = arcade.PhysicsEnginePlatformer(
 80            self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
 81        )
 82
 83        self.background_color = arcade.csscolor.CORNFLOWER_BLUE
 84
 85    def setup(self):
 86        """Set up the game here. Call this function to restart the game."""
 87        pass
 88
 89    def on_draw(self):
 90        """Render the screen."""
 91
 92        # Clear the screen to the background color
 93        self.clear()
 94
 95        # Draw our sprites
 96        self.player_list.draw()
 97        self.wall_list.draw()
 98
 99    def on_update(self, delta_time):
100        """Movement and Game Logic"""
101
102        # Move the player using our physics engine
103        self.physics_engine.update()
104
105    def on_key_press(self, key, modifiers):
106        """Called whenever a key is pressed."""
107
108        if key == arcade.key.UP or key == arcade.key.W:
109            if self.physics_engine.can_jump():
110                self.player_sprite.change_y = PLAYER_JUMP_SPEED
111
112        if key == arcade.key.LEFT or key == arcade.key.A:
113            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
114        elif key == arcade.key.RIGHT or key == arcade.key.D:
115            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
116
117    def on_key_release(self, key, modifiers):
118        """Called whenever a key is released."""
119
120        if key == arcade.key.LEFT or key == arcade.key.A:
121            self.player_sprite.change_x = 0
122        elif key == arcade.key.RIGHT or key == arcade.key.D:
123            self.player_sprite.change_x = 0
124
125
126def main():
127    """Main function"""
128    window = MyGame()
129    window.setup()
130    arcade.run()
131
132
133if __name__ == "__main__":
134    main()

运行本章#

python -m arcade.examples.platform_tutorial.05_add_gravity