Have Enemies Periodically Shoot
Having enemies shoot every x seconds is a bit more complex than shooting randomly as shown in Have Enemies Randomly Shoot. This is because we need to track how often we shoot, and how long it has been since we last shot.
This example uses custom sub-class EnemySprite
. The extra attributes allow
us to track the periodic timing. See the highlighted lines for what is specific
to this example.

sprite_bullets_periodic.py
1"""
2Show how to have enemies shoot bullets at regular intervals.
3
4If Python and Arcade are installed, this example can be run from the command line with:
5python -m arcade.examples.sprite_bullets_periodic
6"""
7import arcade
8
9WINDOW_WIDTH = 1280
10WINDOW_HEIGHT = 720
11WINDOW_TITLE = "Sprites and Periodic Bullets Example"
12
13
14class EnemySprite(arcade.Sprite):
15 """ Enemy ship class that tracks how long it has been since firing. """
16
17 def __init__(self, image_file, scale, bullet_list, time_between_firing):
18 """ Set up the enemy """
19 super().__init__(image_file, scale=scale)
20
21 # How long has it been since we last fired?
22 self.time_since_last_firing = 0.0
23
24 # How often do we fire?
25 self.time_between_firing = time_between_firing
26
27 # When we fire, what list tracks the bullets?
28 self.bullet_list = bullet_list
29
30 def update(self, delta_time: float = 1 / 60):
31 """ Update this sprite. """
32
33 # Track time since we last fired
34 self.time_since_last_firing += delta_time
35
36 # If we are past the firing time, then fire
37 if self.time_since_last_firing >= self.time_between_firing:
38
39 # Reset timer
40 self.time_since_last_firing = 0
41
42 # Fire the bullet
43 bullet = arcade.Sprite(":resources:images/space_shooter/laserBlue01.png")
44 bullet.center_x = self.center_x
45 bullet.angle = 90
46 bullet.top = self.bottom
47 bullet.change_y = -2
48 self.bullet_list.append(bullet)
49
50
51class GameView(arcade.View):
52 """ Main application class """
53
54 def __init__(self):
55 super().__init__()
56
57 self.background_color = arcade.color.BLACK
58
59 self.player = None
60 self.player_list = None
61 self.enemy_list = None
62 self.bullet_list = None
63
64 def setup(self):
65 """ Set up the variables for the game. """
66
67 self.player_list = arcade.SpriteList()
68 self.enemy_list = arcade.SpriteList()
69 self.bullet_list = arcade.SpriteList()
70
71 # Add player ship
72 self.player = arcade.Sprite(
73 ":resources:images/space_shooter/playerShip1_orange.png",
74 scale=0.5,
75 )
76 self.player_list.append(self.player)
77
78 # Add top-left enemy ship
79 enemy = EnemySprite(
80 ":resources:images/space_shooter/playerShip1_green.png",
81 scale=0.5,
82 bullet_list=self.bullet_list,
83 time_between_firing=2.0,
84 )
85 enemy.center_x = 120
86 enemy.center_y = WINDOW_HEIGHT - enemy.height
87 enemy.angle = 180
88 self.enemy_list.append(enemy)
89
90 # Add top-right enemy ship
91 enemy = EnemySprite(":resources:images/space_shooter/playerShip1_green.png",
92 scale=0.5,
93 bullet_list=self.bullet_list,
94 time_between_firing=1.0)
95 enemy.center_x = WINDOW_WIDTH - 120
96 enemy.center_y = WINDOW_HEIGHT - enemy.height
97 enemy.angle = 180
98 self.enemy_list.append(enemy)
99
100 def on_draw(self):
101 """Render the screen. """
102
103 self.clear()
104
105 self.enemy_list.draw()
106 self.bullet_list.draw()
107 self.player_list.draw()
108
109 def on_update(self, delta_time):
110 """ All the logic to move, and the game logic goes here. """
111
112 # Call on_update for each enemy in the list
113 self.enemy_list.update(delta_time)
114
115 # Get rid of the bullet when it flies off-screen
116 for bullet in self.bullet_list:
117 if bullet.top < 0:
118 bullet.remove_from_sprite_lists()
119
120 self.bullet_list.update(delta_time)
121
122 def on_mouse_motion(self, x, y, delta_x, delta_y):
123 """
124 Called whenever the mouse moves.
125 """
126 self.player.center_x = x
127 self.player.center_y = 20
128
129
130def main():
131 """ Main function """
132 # Create a window class. This is what actually shows up on screen
133 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
134
135 # Create and setup the GameView
136 game = GameView()
137 game.setup()
138
139 # Show GameView on screen
140 window.show_view(game)
141
142 # Start the arcade game loop
143 arcade.run()
144
145
146if __name__ == "__main__":
147 main()