1"""
2Acceleration and Friction
3
4Demonstrate how to implement simple acceleration and friction without a
5physics engine.
6
7Artwork from https://kenney.nl
8
9If Python and Arcade are installed, this example can be run from the
10command line with:
11python -m arcade.examples.sprite_move_keyboard_accel
12"""
13
14from __future__ import annotations
15
16import arcade
17
18SPRITE_SCALING = 0.5
19
20SCREEN_WIDTH = 800
21SCREEN_HEIGHT = 600
22SCREEN_TITLE = "Better Move Sprite with Keyboard Example"
23
24# Important constants for this example
25
26# Speed limit
27MAX_SPEED = 3.0
28
29# How fast we accelerate
30ACCELERATION_RATE = 0.1
31
32# How fast to slow down after we let off the key
33FRICTION = 0.02
34
35
36class Player(arcade.Sprite):
37
38 def update(self):
39 self.center_x += self.change_x
40 self.center_y += self.change_y
41
42 # Check to see if we hit the screen edge
43 if self.left < 0:
44 self.left = 0
45 self.change_x = 0 # Zero x speed
46 elif self.right > SCREEN_WIDTH - 1:
47 self.right = SCREEN_WIDTH - 1
48 self.change_x = 0
49
50 if self.bottom < 0:
51 self.bottom = 0
52 self.change_y = 0
53 elif self.top > SCREEN_HEIGHT - 1:
54 self.top = SCREEN_HEIGHT - 1
55 self.change_y = 0
56
57
58class MyGame(arcade.Window):
59 """
60 Main application class.
61 """
62
63 def __init__(self, width, height, title):
64 """
65 Initializer
66 """
67
68 # Call the parent class initializer
69 super().__init__(width, height, title)
70
71 # Variable to will hold the player sprite list
72 self.player_list = None
73
74 # Create a place to store the player sprite
75 # so it can be accessed directly.
76 self.player_sprite = None
77
78 # Create places to store the speed display Text objects
79 self.x_speed_display = None
80 self.y_speed_display = None
81
82 # Track the current state of what key is pressed
83 self.left_pressed = False
84 self.right_pressed = False
85 self.up_pressed = False
86 self.down_pressed = False
87
88 # Set the background color
89 arcade.background_color = arcade.color.AMAZON
90
91 def setup(self):
92 """ Set up the game and initialize the variables. """
93
94 # Create a sprite list
95 self.player_list = arcade.SpriteList()
96
97 # Set up the player
98 self.player_sprite = Player(":resources:images/animated_characters/female_person/femalePerson_idle.png",
99 scale=SPRITE_SCALING)
100 self.player_sprite.position = self.width / 2, self.height / 2
101 self.player_list.append(self.player_sprite)
102
103 # Create the speed display objects with initial text
104 self.x_speed_display = arcade.Text(
105 f"X Speed: {self.player_sprite.change_x:6.3f}",
106 10, 50, arcade.color.BLACK)
107
108 self.y_speed_display = arcade.Text(
109 f"Y Speed: {self.player_sprite.change_y:6.3f}",
110 10, 70, arcade.color.BLACK)
111
112 def on_draw(self):
113 """
114 Render the screen.
115 """
116
117 # This command has to happen before we start drawing
118 self.clear()
119
120 # Draw all the sprites.
121 self.player_list.draw()
122
123 # Draw the speed indicators
124 self.x_speed_display.draw()
125 self.y_speed_display.draw()
126
127 def on_update(self, delta_time):
128 """ Movement and game logic """
129
130 # Add some friction
131 if self.player_sprite.change_x > FRICTION:
132 self.player_sprite.change_x -= FRICTION
133 elif self.player_sprite.change_x < -FRICTION:
134 self.player_sprite.change_x += FRICTION
135 else:
136 self.player_sprite.change_x = 0
137
138 if self.player_sprite.change_y > FRICTION:
139 self.player_sprite.change_y -= FRICTION
140 elif self.player_sprite.change_y < -FRICTION:
141 self.player_sprite.change_y += FRICTION
142 else:
143 self.player_sprite.change_y = 0
144
145 # Apply acceleration based on the keys pressed
146 if self.up_pressed and not self.down_pressed:
147 self.player_sprite.change_y += ACCELERATION_RATE
148 elif self.down_pressed and not self.up_pressed:
149 self.player_sprite.change_y += -ACCELERATION_RATE
150 if self.left_pressed and not self.right_pressed:
151 self.player_sprite.change_x += -ACCELERATION_RATE
152 elif self.right_pressed and not self.left_pressed:
153 self.player_sprite.change_x += ACCELERATION_RATE
154
155 if self.player_sprite.change_x > MAX_SPEED:
156 self.player_sprite.change_x = MAX_SPEED
157 elif self.player_sprite.change_x < -MAX_SPEED:
158 self.player_sprite.change_x = -MAX_SPEED
159 if self.player_sprite.change_y > MAX_SPEED:
160 self.player_sprite.change_y = MAX_SPEED
161 elif self.player_sprite.change_y < -MAX_SPEED:
162 self.player_sprite.change_y = -MAX_SPEED
163
164 # Call update to move the sprite
165 # IMPORTANT: If using a physics engine, you need to call update
166 # on it instead of the sprite list!
167 self.player_list.update()
168
169 # Update the speed displays based on the final speed
170 self.x_speed_display.text = f"X Speed: {self.player_sprite.change_x:6.3f}"
171 self.y_speed_display.text = f"Y Speed: {self.player_sprite.change_y:6.3f}"
172
173 def on_key_press(self, key, modifiers):
174 """Called whenever a key is pressed. """
175
176 if key == arcade.key.UP:
177 self.up_pressed = True
178 elif key == arcade.key.DOWN:
179 self.down_pressed = True
180 elif key == arcade.key.LEFT:
181 self.left_pressed = True
182 elif key == arcade.key.RIGHT:
183 self.right_pressed = True
184
185 def on_key_release(self, key, modifiers):
186 """Called when the user releases a key. """
187
188 if key == arcade.key.UP:
189 self.up_pressed = False
190 elif key == arcade.key.DOWN:
191 self.down_pressed = False
192 elif key == arcade.key.LEFT:
193 self.left_pressed = False
194 elif key == arcade.key.RIGHT:
195 self.right_pressed = False
196
197
198def main():
199 """ Main function """
200 window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
201 window.setup()
202 arcade.run()
203
204
205if __name__ == "__main__":
206 main()