Moving Platforms

sprite_moving_platforms.py
  1"""
  2Sprite with Moving Platforms
  3
  4Artwork from https://kenney.nl
  5
  6If Python and Arcade are installed, this example can be run from the command line with:
  7python -m arcade.examples.sprite_moving_platforms
  8"""
  9import arcade
 10
 11SPRITE_SCALING = 0.5
 12
 13WINDOW_WIDTH = 1289
 14WINDOW_HEIGHT = 720
 15WINDOW_TITLE = "Sprite with Moving Platforms Example"
 16SPRITE_PIXEL_SIZE = 128
 17GRID_PIXEL_SIZE = (SPRITE_PIXEL_SIZE * SPRITE_SCALING)
 18
 19# How many pixels to keep as a minimum margin between the character
 20# and the edge of the screen.
 21VIEWPORT_MARGIN = SPRITE_PIXEL_SIZE * SPRITE_SCALING
 22RIGHT_MARGIN = 4 * SPRITE_PIXEL_SIZE * SPRITE_SCALING
 23
 24# Physics
 25MOVEMENT_SPEED = 10 * SPRITE_SCALING
 26JUMP_SPEED = 28 * SPRITE_SCALING
 27GRAVITY = .9 * SPRITE_SCALING
 28
 29# How fast the camera pans to the player. 1.0 is instant.
 30CAMERA_SPEED = 0.1
 31
 32
 33class GameView(arcade.View):
 34    """ Main application class. """
 35
 36    def __init__(self):
 37        """ Initializer """
 38
 39        # Call the parent init
 40        super().__init__()
 41
 42        # Sprite lists
 43
 44        # Drawing non-moving walls separate from moving walls improves performance.
 45        self.static_wall_list = None
 46        self.moving_platform_list = None
 47
 48        self.player_list = None
 49
 50        # Set up the player
 51        self.player_sprite = None
 52        self.physics_engine = None
 53        self.game_over = False
 54
 55        # Create the cameras. One for the GUI, one for the sprites.
 56        # We scroll the 'sprite world' but not the GUI.
 57        self.camera_sprites = arcade.camera.Camera2D()
 58        self.camera_gui = arcade.camera.Camera2D()
 59
 60        self.left_down = False
 61        self.right_down = False
 62
 63    def setup(self):
 64        """ Set up the game and initialize the variables. """
 65
 66        # Sprite lists
 67        self.static_wall_list = arcade.SpriteList()
 68        self.moving_platform_list = arcade.SpriteList()
 69        self.player_list = arcade.SpriteList()
 70
 71        # Set up the player
 72        self.player_sprite = arcade.Sprite(
 73            ":resources:images/animated_characters/female_person/femalePerson_idle.png",
 74            scale=SPRITE_SCALING,
 75        )
 76        self.player_sprite.center_x = 2 * GRID_PIXEL_SIZE
 77        self.player_sprite.center_y = 3 * GRID_PIXEL_SIZE
 78        self.player_list.append(self.player_sprite)
 79
 80        # Create floor
 81        for i in range(50):
 82            wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=SPRITE_SCALING)
 83            wall.bottom = 0
 84            wall.center_x = - 1000 + i * GRID_PIXEL_SIZE
 85            self.static_wall_list.append(wall)
 86
 87        # Create platform side to side
 88        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=SPRITE_SCALING)
 89        wall.center_y = 3 * GRID_PIXEL_SIZE
 90        wall.center_x = 3 * GRID_PIXEL_SIZE
 91        wall.boundary_left = 2 * GRID_PIXEL_SIZE
 92        wall.boundary_right = 5 * GRID_PIXEL_SIZE
 93        wall.change_x = 2 * SPRITE_SCALING
 94        self.moving_platform_list.append(wall)
 95
 96        # Create platform side to side
 97        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=SPRITE_SCALING)
 98        wall.center_y = 3 * GRID_PIXEL_SIZE
 99        wall.center_x = 7 * GRID_PIXEL_SIZE
100        wall.boundary_left = 5 * GRID_PIXEL_SIZE
101        wall.boundary_right = 9 * GRID_PIXEL_SIZE
102        wall.change_x = -2 * SPRITE_SCALING
103        self.moving_platform_list.append(wall)
104
105        # Create platform moving up and down
106        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=SPRITE_SCALING)
107        wall.center_y = 5 * GRID_PIXEL_SIZE
108        wall.center_x = 5 * GRID_PIXEL_SIZE
109        wall.boundary_top = 8 * GRID_PIXEL_SIZE
110        wall.boundary_bottom = 4 * GRID_PIXEL_SIZE
111        wall.change_y = 2 * SPRITE_SCALING
112        self.moving_platform_list.append(wall)
113
114        # Create platform moving diagonally
115        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=SPRITE_SCALING)
116        wall.center_y = 5 * GRID_PIXEL_SIZE
117        wall.center_x = 8 * GRID_PIXEL_SIZE
118        wall.boundary_left = 7 * GRID_PIXEL_SIZE
119        wall.boundary_right = 9 * GRID_PIXEL_SIZE
120        wall.boundary_top = 8 * GRID_PIXEL_SIZE
121        wall.boundary_bottom = 4 * GRID_PIXEL_SIZE
122        wall.change_x = 2 * SPRITE_SCALING
123        wall.change_y = 2 * SPRITE_SCALING
124        self.moving_platform_list.append(wall)
125
126        # Create our physics engine
127        self.physics_engine = arcade.PhysicsEnginePlatformer(
128            self.player_sprite,
129            platforms=self.moving_platform_list,
130            walls=self.static_wall_list,
131            gravity_constant=GRAVITY
132        )
133
134        # Set the background color
135        self.background_color = arcade.color.AMAZON
136
137        self.game_over = False
138
139    def on_draw(self):
140        """
141        Render the screen.
142        """
143
144        # This command has to happen before we start drawing
145        self.clear()
146
147        # Select the camera we'll use to draw all our sprites
148        with self.camera_sprites.activate():
149            # Draw the sprites
150            self.static_wall_list.draw()
151            self.moving_platform_list.draw()
152            self.player_list.draw()
153
154        # Update & draw our text to the screen
155        with self.camera_gui.activate():
156            distance = self.player_sprite.right
157            output = f"Distance: {distance}"
158            arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)
159
160    def set_x_speed(self):
161        if self.left_down and not self.right_down:
162            self.player_sprite.change_x = -MOVEMENT_SPEED
163        elif self.right_down and not self.left_down:
164            self.player_sprite.change_x = MOVEMENT_SPEED
165        else:
166            self.player_sprite.change_x = 0
167
168    def on_key_press(self, key, modifiers):
169        """ Called whenever the mouse moves. """
170        if key == arcade.key.UP:
171            if self.physics_engine.can_jump():
172                self.player_sprite.change_y = JUMP_SPEED
173        elif key == arcade.key.LEFT:
174            self.left_down = True
175            self.set_x_speed()
176        elif key == arcade.key.RIGHT:
177            self.right_down = True
178            self.set_x_speed()
179
180    def on_key_release(self, key, modifiers):
181        """ Called when the user presses a mouse button. """
182        if key == arcade.key.LEFT:
183            self.left_down = False
184            self.set_x_speed()
185        elif key == arcade.key.RIGHT:
186            self.right_down = False
187            self.set_x_speed()
188
189    def on_update(self, delta_time):
190        """ Movement and game logic """
191
192        # Call update on all sprites
193        self.physics_engine.update()
194
195        # Scroll the screen to the player
196        self.scroll_to_player()
197
198    def scroll_to_player(self):
199        """
200        Scroll the window to the player.
201
202        if CAMERA_SPEED is 1, the camera will immediately move to the desired position.
203        Anything between 0 and 1 will have the camera move to the location with a smoother
204        pan.
205        """
206
207        position = (self.player_sprite.center_x, self.player_sprite.center_y)
208        self.camera_sprites.position = arcade.math.lerp_2d(
209            self.camera_sprites.position,
210            position,
211            CAMERA_SPEED,
212        )
213
214
215def main():
216    """ Main function """
217    # Create a window class. This is what actually shows up on screen
218    window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
219
220    # Create and setup the GameView
221    game = GameView()
222    game.setup()
223
224    # Show GameView on screen
225    window.show_view(game)
226
227    # Start the arcade game loop
228    arcade.run()
229
230
231if __name__ == "__main__":
232    main()