Acceleration and Friction

Screen shot of moving a sprite by keyboard
sprite_move_keyboard_accel.py
  1"""
  2Show how to use acceleration and friction
  3
  4Artwork from http://kenney.nl
  5
  6If Python and Arcade are installed, this example can be run from the command line with:
  7python -m arcade.examples.sprite_move_keyboard_accel
  8"""
  9
 10import arcade
 11import os
 12
 13SPRITE_SCALING = 0.5
 14
 15SCREEN_WIDTH = 800
 16SCREEN_HEIGHT = 600
 17SCREEN_TITLE = "Better Move Sprite with Keyboard Example"
 18
 19# Important constants for this example
 20
 21# Speed limit
 22MAX_SPEED = 3.0
 23
 24# How fast we accelerate
 25ACCELERATION_RATE = 0.1
 26
 27# How fast to slow down after we letr off the key
 28FRICTION = 0.02
 29
 30class Player(arcade.Sprite):
 31
 32    def update(self):
 33        self.center_x += self.change_x
 34        self.center_y += self.change_y
 35
 36        # Check to see if we hit the screen edge
 37        if self.left < 0:
 38            self.left = 0
 39            self.change_x = 0 # Zero x speed
 40        elif self.right > SCREEN_WIDTH - 1:
 41            self.right = SCREEN_WIDTH - 1
 42            self.change_x = 0
 43
 44        if self.bottom < 0:
 45            self.bottom = 0
 46            self.change_y = 0
 47        elif self.top > SCREEN_HEIGHT - 1:
 48            self.top = SCREEN_HEIGHT - 1
 49            self.change_y = 0
 50
 51
 52class MyGame(arcade.Window):
 53    """
 54    Main application class.
 55    """
 56
 57    def __init__(self, width, height, title):
 58        """
 59        Initializer
 60        """
 61
 62        # Call the parent class initializer
 63        super().__init__(width, height, title)
 64
 65        # Set the working directory (where we expect to find files) to the same
 66        # directory this .py file is in. You can leave this out of your own
 67        # code, but it is needed to easily run the examples using "python -m"
 68        # as mentioned at the top of this program.
 69        file_path = os.path.dirname(os.path.abspath(__file__))
 70        os.chdir(file_path)
 71
 72        # Variables that will hold sprite lists
 73        self.player_list = None
 74
 75        # Set up the player info
 76        self.player_sprite = None
 77
 78        # Track the current state of what key is pressed
 79        self.left_pressed = False
 80        self.right_pressed = False
 81        self.up_pressed = False
 82        self.down_pressed = False
 83
 84        # Set the background color
 85        arcade.set_background_color(arcade.color.AMAZON)
 86
 87    def setup(self):
 88        """ Set up the game and initialize the variables. """
 89
 90        # Sprite lists
 91        self.player_list = arcade.SpriteList()
 92
 93        # Set up the player
 94        self.player_sprite = Player(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING)
 95        self.player_sprite.center_x = 50
 96        self.player_sprite.center_y = 50
 97        self.player_list.append(self.player_sprite)
 98
 99    def on_draw(self):
100        """
101        Render the screen.
102        """
103
104        # This command has to happen before we start drawing
105        arcade.start_render()
106
107        # Draw all the sprites.
108        self.player_list.draw()
109
110        # Display speed
111        arcade.draw_text(f"X Speed: {self.player_sprite.change_x:6.3f}", 10, 50, arcade.color.BLACK)
112        arcade.draw_text(f"Y Speed: {self.player_sprite.change_y:6.3f}", 10, 70, arcade.color.BLACK)
113
114    def on_update(self, delta_time):
115        """ Movement and game logic """
116
117        # Add some friction
118        if self.player_sprite.change_x > FRICTION:
119            self.player_sprite.change_x -= FRICTION
120        elif self.player_sprite.change_x < -FRICTION:
121            self.player_sprite.change_x += FRICTION
122        else:
123            self.player_sprite.change_x = 0
124
125        if self.player_sprite.change_y > FRICTION:
126            self.player_sprite.change_y -= FRICTION
127        elif self.player_sprite.change_y < -FRICTION:
128            self.player_sprite.change_y += FRICTION
129        else:
130            self.player_sprite.change_y = 0
131
132        # Apply acceleration based on the keys pressed
133        if self.up_pressed and not self.down_pressed:
134            self.player_sprite.change_y += ACCELERATION_RATE
135        elif self.down_pressed and not self.up_pressed:
136            self.player_sprite.change_y += -ACCELERATION_RATE
137        if self.left_pressed and not self.right_pressed:
138            self.player_sprite.change_x += -ACCELERATION_RATE
139        elif self.right_pressed and not self.left_pressed:
140            self.player_sprite.change_x += ACCELERATION_RATE
141
142        if self.player_sprite.change_x > MAX_SPEED:
143            self.player_sprite.change_x = MAX_SPEED
144        elif self.player_sprite.change_x < -MAX_SPEED:
145            self.player_sprite.change_x = -MAX_SPEED
146        if self.player_sprite.change_y > MAX_SPEED:
147            self.player_sprite.change_y = MAX_SPEED
148        elif self.player_sprite.change_y < -MAX_SPEED:
149            self.player_sprite.change_y = -MAX_SPEED
150
151        # Call update to move the sprite
152        # If using a physics engine, call update on it instead of the sprite
153        # list.
154        self.player_list.update()
155
156    def on_key_press(self, key, modifiers):
157        """Called whenever a key is pressed. """
158
159        if key == arcade.key.UP:
160            self.up_pressed = True
161        elif key == arcade.key.DOWN:
162            self.down_pressed = True
163        elif key == arcade.key.LEFT:
164            self.left_pressed = True
165        elif key == arcade.key.RIGHT:
166            self.right_pressed = True
167
168    def on_key_release(self, key, modifiers):
169        """Called when the user releases a key. """
170
171        if key == arcade.key.UP:
172            self.up_pressed = False
173        elif key == arcade.key.DOWN:
174            self.down_pressed = False
175        elif key == arcade.key.LEFT:
176            self.left_pressed = False
177        elif key == arcade.key.RIGHT:
178            self.right_pressed = False
179
180
181def main():
182    """ Main method """
183    window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
184    window.setup()
185    arcade.run()
186
187
188if __name__ == "__main__":
189    main()