Sprites That Follow 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
12import arcade
13import math
14
15# --- Constants ---
16SPRITE_SCALING_PLAYER = 0.5
17SPRITE_SCALING_ENEMY = 0.5
18ENEMY_SPEED = 5.0
19
20WINDOW_WIDTH = 1289
21WINDOW_HEIGHT = 720
22WINDOW_TITLE = "Sprite Follow Path Simple Example"
23
24
25class Enemy(arcade.Sprite):
26 """
27 This class represents the Enemy on our screen.
28 """
29
30 def __init__(self, image, scale, position_list):
31 super().__init__(image, scale=scale)
32 self.position_list = position_list
33 self.cur_position = 0
34 self.speed = ENEMY_SPEED
35
36 def update(self, delta_time: float = 1 / 60):
37 """Have a sprite follow a path"""
38 # Where are we
39 start_x = self.center_x
40 start_y = self.center_y
41
42 # Where are we going
43 dest_x = self.position_list[self.cur_position][0]
44 dest_y = self.position_list[self.cur_position][1]
45
46 # X and Y diff between the two
47 x_diff = dest_x - start_x
48 y_diff = dest_y - start_y
49
50 # Calculate angle to get there
51 angle = math.atan2(y_diff, x_diff)
52
53 # How far are we?
54 distance = math.sqrt((self.center_x - dest_x) ** 2 + (self.center_y - dest_y) ** 2)
55
56 # How fast should we go? If we are close to our destination,
57 # lower our speed so we don't overshoot.
58 speed = min(self.speed, distance)
59
60 # Calculate vector to travel
61 change_x = math.cos(angle) * speed
62 change_y = math.sin(angle) * speed
63
64 # Update our location
65 self.center_x += change_x
66 self.center_y += change_y
67
68 # How far are we?
69 distance = math.sqrt((self.center_x - dest_x) ** 2 + (self.center_y - dest_y) ** 2)
70
71 # If we are there, head to the next point.
72 if distance <= self.speed:
73 self.cur_position += 1
74
75 # Reached the end of the list, start over.
76 if self.cur_position >= len(self.position_list):
77 self.cur_position = 0
78
79
80class GameView(arcade.View):
81
82 def __init__(self):
83 """ Initializer """
84 # Call the parent class initializer
85 super().__init__()
86
87 # Variables that will hold sprite lists
88 self.player_list = None
89 self.enemy_list = None
90
91 # Set up the player info
92 self.player_sprite = None
93 self.score = 0
94
95 # Don't show the mouse cursor
96 self.window.set_mouse_visible(False)
97
98 self.background_color = arcade.color.AMAZON
99
100 def setup(self):
101 """ Set up the game and initialize the variables. """
102
103 # Sprite lists
104 self.player_list = arcade.SpriteList()
105 self.enemy_list = arcade.SpriteList()
106
107 # Score
108 self.score = 0
109
110 # Set up the player
111 # Character image from kenney.nl
112 self.player_sprite = arcade.Sprite(
113 ":resources:images/animated_characters/female_person/femalePerson_idle.png",
114 scale=SPRITE_SCALING_PLAYER)
115 self.player_sprite.center_x = 50
116 self.player_sprite.center_y = 50
117 self.player_list.append(self.player_sprite)
118
119 # List of points the enemy will travel too.
120 position_list = [
121 [50, 50],
122 [self.width - 50, 50],
123 [self.width - 50, self.height - 50],
124 [50, self.height - 50],
125 ]
126 # Spawn a few enemies
127 self.spawn_enemy((50, 50), position_list)
128 self.spawn_enemy((50, 250), position_list)
129 self.spawn_enemy((50, 450), position_list)
130 self.spawn_enemy((50, 650), position_list)
131
132 def spawn_enemy(self, position, position_list):
133 # Spawn a new enemy
134 enemy = Enemy(":resources:images/animated_characters/robot/robot_idle.png",
135 SPRITE_SCALING_ENEMY,
136 position_list)
137 # Set initial location of the enemy at the first point
138 enemy.position = position
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 # Move the center of the player sprite to match the mouse x, y
150 self.player_sprite.center_x = x
151 self.player_sprite.center_y = y
152
153 def on_update(self, delta_time):
154 """ Movement and game logic """
155 self.enemy_list.update()
156
157 def on_key_press(self, symbol: int, modifiers: int):
158 if symbol == arcade.key.ESCAPE:
159 self.window.close()
160
161
162def main():
163 """ Main function """
164 # Create a window class. This is what actually shows up on screen
165 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
166
167 # Create and setup the GameView
168 game = GameView()
169 game.setup()
170
171 # Show GameView on screen
172 window.show_view(game)
173
174 # Start the arcade game loop
175 arcade.run()
176
177
178if __name__ == "__main__":
179 main()