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()