Moving Platforms

sprite_moving_platforms.py
  1"""
  2Sprite with Moving Platforms
  3
  4Load a map stored in csv format, as exported by the program 'Tiled.'
  5
  6Artwork from http://kenney.nl
  7
  8If Python and Arcade are installed, this example can be run from the command line with:
  9python -m arcade.examples.sprite_moving_platforms
 10"""
 11import arcade
 12
 13SPRITE_SCALING = 0.5
 14
 15SCREEN_WIDTH = 1000
 16SCREEN_HEIGHT = 600
 17SCREEN_TITLE = "Sprite with Moving Platforms Example"
 18SPRITE_PIXEL_SIZE = 128
 19GRID_PIXEL_SIZE = (SPRITE_PIXEL_SIZE * SPRITE_SCALING)
 20
 21# How many pixels to keep as a minimum margin between the character
 22# and the edge of the screen.
 23VIEWPORT_MARGIN = SPRITE_PIXEL_SIZE * SPRITE_SCALING
 24RIGHT_MARGIN = 4 * SPRITE_PIXEL_SIZE * SPRITE_SCALING
 25
 26# Physics
 27MOVEMENT_SPEED = 10 * SPRITE_SCALING
 28JUMP_SPEED = 28 * SPRITE_SCALING
 29GRAVITY = .9 * SPRITE_SCALING
 30
 31
 32class MyGame(arcade.Window):
 33    """ Main application class. """
 34
 35    def __init__(self, width, height, title):
 36        """
 37        Initializer
 38        """
 39
 40        super().__init__(width, height, title)
 41
 42        # Sprite lists
 43
 44        # We use an all-wall list to check for collisions.
 45        self.all_wall_list = None
 46
 47        # Drawing non-moving walls separate from moving walls improves performance.
 48        self.static_wall_list = None
 49        self.moving_wall_list = None
 50
 51        self.player_list = None
 52
 53        # Set up the player
 54        self.player_sprite = None
 55        self.physics_engine = None
 56        self.view_left = 0
 57        self.view_bottom = 0
 58        self.end_of_map = 0
 59        self.game_over = False
 60
 61    def setup(self):
 62        """ Set up the game and initialize the variables. """
 63
 64        # Sprite lists
 65        self.all_wall_list = arcade.SpriteList()
 66        self.static_wall_list = arcade.SpriteList()
 67        self.moving_wall_list = arcade.SpriteList()
 68        self.player_list = arcade.SpriteList()
 69
 70        # Set up the player
 71        self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING)
 72        self.player_sprite.center_x = 2 * GRID_PIXEL_SIZE
 73        self.player_sprite.center_y = 3 * GRID_PIXEL_SIZE
 74        self.player_list.append(self.player_sprite)
 75
 76        # Create floor
 77        for i in range(30):
 78            wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
 79            wall.bottom = 0
 80            wall.center_x = i * GRID_PIXEL_SIZE
 81            self.static_wall_list.append(wall)
 82            self.all_wall_list.append(wall)
 83
 84        # Create platform side to side
 85        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
 86        wall.center_y = 3 * GRID_PIXEL_SIZE
 87        wall.center_x = 3 * GRID_PIXEL_SIZE
 88        wall.boundary_left = 2 * GRID_PIXEL_SIZE
 89        wall.boundary_right = 5 * GRID_PIXEL_SIZE
 90        wall.change_x = 2 * SPRITE_SCALING
 91
 92        self.all_wall_list.append(wall)
 93        self.moving_wall_list.append(wall)
 94
 95        # Create platform side to side
 96        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
 97        wall.center_y = 3 * GRID_PIXEL_SIZE
 98        wall.center_x = 7 * GRID_PIXEL_SIZE
 99        wall.boundary_left = 5 * GRID_PIXEL_SIZE
100        wall.boundary_right = 9 * GRID_PIXEL_SIZE
101        wall.change_x = -2 * SPRITE_SCALING
102
103        self.all_wall_list.append(wall)
104        self.moving_wall_list.append(wall)
105
106        # Create platform moving up and down
107        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", 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
114        self.all_wall_list.append(wall)
115        self.moving_wall_list.append(wall)
116
117        # Create platform moving diagonally
118        wall = arcade.Sprite(":resources:images/tiles/grassMid.png", SPRITE_SCALING)
119        wall.center_y = 5 * GRID_PIXEL_SIZE
120        wall.center_x = 8 * GRID_PIXEL_SIZE
121        wall.boundary_left = 7 * GRID_PIXEL_SIZE
122        wall.boundary_right = 9 * GRID_PIXEL_SIZE
123
124        wall.boundary_top = 8 * GRID_PIXEL_SIZE
125        wall.boundary_bottom = 4 * GRID_PIXEL_SIZE
126        wall.change_x = 2 * SPRITE_SCALING
127        wall.change_y = 2 * SPRITE_SCALING
128
129        self.all_wall_list.append(wall)
130        self.moving_wall_list.append(wall)
131
132        self.physics_engine = \
133            arcade.PhysicsEnginePlatformer(self.player_sprite,
134                                           self.all_wall_list,
135                                           gravity_constant=GRAVITY)
136
137        # Set the background color
138        arcade.set_background_color(arcade.color.AMAZON)
139
140        # Set the viewport boundaries
141        # These numbers set where we have 'scrolled' to.
142        self.view_left = 0
143        self.view_bottom = 0
144
145        self.game_over = False
146
147    def on_draw(self):
148        """
149        Render the screen.
150        """
151
152        # This command has to happen before we start drawing
153        arcade.start_render()
154
155        # Draw the sprites.
156        self.static_wall_list.draw()
157        self.moving_wall_list.draw()
158        self.player_list.draw()
159
160        # Put the text on the screen.
161        # Adjust the text position based on the viewport so that we don't
162        # scroll the text too.
163        distance = self.player_sprite.right
164        output = f"Distance: {distance}"
165        arcade.draw_text(output, self.view_left + 10, self.view_bottom + 20,
166                         arcade.color.WHITE, 14)
167
168    def on_key_press(self, key, modifiers):
169        """
170        Called whenever the mouse moves.
171        """
172        if key == arcade.key.UP:
173            if self.physics_engine.can_jump():
174                self.player_sprite.change_y = JUMP_SPEED
175        elif key == arcade.key.LEFT:
176            self.player_sprite.change_x = -MOVEMENT_SPEED
177        elif key == arcade.key.RIGHT:
178            self.player_sprite.change_x = MOVEMENT_SPEED
179
180    def on_key_release(self, key, modifiers):
181        """
182        Called when the user presses a mouse button.
183        """
184        if key == arcade.key.LEFT or key == arcade.key.RIGHT:
185            self.player_sprite.change_x = 0
186
187    def on_update(self, delta_time):
188        """ Movement and game logic """
189
190        # Call update on all sprites
191        self.physics_engine.update()
192
193        # --- Manage Scrolling ---
194
195        # Track if we need to change the viewport
196
197        changed = False
198
199        # Scroll left
200        left_boundary = self.view_left + VIEWPORT_MARGIN
201        if self.player_sprite.left < left_boundary:
202            self.view_left -= left_boundary - self.player_sprite.left
203            changed = True
204
205        # Scroll right
206        right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_MARGIN
207        if self.player_sprite.right > right_boundary:
208            self.view_left += self.player_sprite.right - right_boundary
209            changed = True
210
211        # Scroll up
212        top_boundary = self.view_bottom + SCREEN_HEIGHT - VIEWPORT_MARGIN
213        if self.player_sprite.top > top_boundary:
214            self.view_bottom += self.player_sprite.top - top_boundary
215            changed = True
216
217        # Scroll down
218        bottom_boundary = self.view_bottom + VIEWPORT_MARGIN
219        if self.player_sprite.bottom < bottom_boundary:
220            self.view_bottom -= bottom_boundary - self.player_sprite.bottom
221            changed = True
222
223        # If we need to scroll, go ahead and do it.
224        if changed:
225            arcade.set_viewport(self.view_left,
226                                SCREEN_WIDTH + self.view_left,
227                                self.view_bottom,
228                                SCREEN_HEIGHT + self.view_bottom)
229
230
231def main():
232    """ Main method """
233    window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
234    window.setup()
235    arcade.run()
236
237
238if __name__ == "__main__":
239    main()