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