Sprites That Follow a Path#

Screen shot of a sprite following a path
follow_path.py#
  1"""
  2Sprite Follow Path
  3
  4This example has enemy sprites follow a set path.
  5
  6Artwork from https://kenney.nl
  7
  8If Python and Arcade are installed, this example can be run from the command line with:
  9python -m arcade.examples.follow_path
 10"""
 11
 12from __future__ import annotations
 13
 14import arcade
 15import math
 16
 17# --- Constants ---
 18SPRITE_SCALING_PLAYER = 0.5
 19SPRITE_SCALING_ENEMY = 0.5
 20ENEMY_SPEED = 3.0
 21
 22SCREEN_WIDTH = 800
 23SCREEN_HEIGHT = 600
 24SCREEN_TITLE = "Sprite Follow Path Simple Example"
 25
 26
 27class Enemy(arcade.Sprite):
 28    """
 29    This class represents the Enemy on our screen.
 30    """
 31
 32    def __init__(self, image, scale, position_list):
 33        super().__init__(image, scale=scale)
 34        self.position_list = position_list
 35        self.cur_position = 0
 36        self.speed = ENEMY_SPEED
 37
 38    def update(self):
 39        """ Have a sprite follow a path """
 40
 41        # Where are we
 42        start_x = self.center_x
 43        start_y = self.center_y
 44
 45        # Where are we going
 46        dest_x = self.position_list[self.cur_position][0]
 47        dest_y = self.position_list[self.cur_position][1]
 48
 49        # X and Y diff between the two
 50        x_diff = dest_x - start_x
 51        y_diff = dest_y - start_y
 52
 53        # Calculate angle to get there
 54        angle = math.atan2(y_diff, x_diff)
 55
 56        # How far are we?
 57        distance = math.sqrt((self.center_x - dest_x) ** 2 + (self.center_y - dest_y) ** 2)
 58
 59        # How fast should we go? If we are close to our destination,
 60        # lower our speed so we don't overshoot.
 61        speed = min(self.speed, distance)
 62
 63        # Calculate vector to travel
 64        change_x = math.cos(angle) * speed
 65        change_y = math.sin(angle) * speed
 66
 67        # Update our location
 68        self.center_x += change_x
 69        self.center_y += change_y
 70
 71        # How far are we?
 72        distance = math.sqrt((self.center_x - dest_x) ** 2 + (self.center_y - dest_y) ** 2)
 73
 74        # If we are there, head to the next point.
 75        if distance <= self.speed:
 76            self.cur_position += 1
 77
 78            # Reached the end of the list, start over.
 79            if self.cur_position >= len(self.position_list):
 80                self.cur_position = 0
 81
 82
 83class MyGame(arcade.Window):
 84    """ Our custom Window Class"""
 85
 86    def __init__(self):
 87        """ Initializer """
 88        # Call the parent class initializer
 89        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 90
 91        # Variables that will hold sprite lists
 92        self.player_list = None
 93        self.enemy_list = None
 94
 95        # Set up the player info
 96        self.player_sprite = None
 97        self.score = 0
 98
 99        # Don't show the mouse cursor
100        self.set_mouse_visible(False)
101
102        self.background_color = arcade.color.AMAZON
103
104    def setup(self):
105        """ Set up the game and initialize the variables. """
106
107        # Sprite lists
108        self.player_list = arcade.SpriteList()
109        self.enemy_list = arcade.SpriteList()
110
111        # Score
112        self.score = 0
113
114        # Set up the player
115        # Character image from kenney.nl
116        self.player_sprite = arcade.Sprite(
117            ":resources:images/animated_characters/female_person/femalePerson_idle.png",
118            scale=SPRITE_SCALING_PLAYER)
119        self.player_sprite.center_x = 50
120        self.player_sprite.center_y = 50
121        self.player_list.append(self.player_sprite)
122
123        # List of points the enemy will travel too.
124        position_list = [[50, 50],
125                         [700, 50],
126                         [700, 500],
127                         [50, 500]]
128
129        # Create the enemy
130        enemy = Enemy(":resources:images/animated_characters/robot/robot_idle.png",
131                      SPRITE_SCALING_ENEMY,
132                      position_list)
133
134        # Set initial location of the enemy at the first point
135        enemy.center_x = position_list[0][0]
136        enemy.center_x = position_list[0][1]
137
138        # Add the enemy to the enemy list
139        self.enemy_list.append(enemy)
140
141    def on_draw(self):
142        """ Draw everything """
143        self.clear()
144        self.enemy_list.draw()
145        self.player_list.draw()
146
147    def on_mouse_motion(self, x, y, dx, dy):
148        """ Handle Mouse Motion """
149
150        # Move the center of the player sprite to match the mouse x, y
151        self.player_sprite.center_x = x
152        self.player_sprite.center_y = y
153
154    def on_update(self, delta_time):
155        """ Movement and game logic """
156        self.enemy_list.update()
157
158
159def main():
160    """ Main function """
161    window = MyGame()
162    window.setup()
163    arcade.run()
164
165
166if __name__ == "__main__":
167    main()