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