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.
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
9SCREEN_WIDTH = 800
10SCREEN_HEIGHT = 600
11SCREEN_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)
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 on_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 MyGame(arcade.Window):
52 """ Main application class """
53
54 def __init__(self):
55 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
56
57 arcade.set_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 """ Setup 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(":resources:images/space_shooter/playerShip1_orange.png", 0.5)
73 self.player_list.append(self.player)
74
75 # Add top-left enemy ship
76 enemy = EnemySprite(":resources:images/space_shooter/playerShip1_green.png",
77 scale=0.5,
78 bullet_list=self.bullet_list,
79 time_between_firing=2.0)
80 enemy.center_x = 120
81 enemy.center_y = SCREEN_HEIGHT - enemy.height
82 enemy.angle = 180
83 self.enemy_list.append(enemy)
84
85 # Add top-right enemy ship
86 enemy = EnemySprite(":resources:images/space_shooter/playerShip1_green.png",
87 scale=0.5,
88 bullet_list=self.bullet_list,
89 time_between_firing=1.0)
90 enemy.center_x = SCREEN_WIDTH - 120
91 enemy.center_y = SCREEN_HEIGHT - enemy.height
92 enemy.angle = 180
93 self.enemy_list.append(enemy)
94
95 def on_draw(self):
96 """Render the screen. """
97
98 arcade.start_render()
99
100 self.enemy_list.draw()
101 self.bullet_list.draw()
102 self.player_list.draw()
103
104 def on_update(self, delta_time):
105 """ All the logic to move, and the game logic goes here. """
106
107 # Call on_update for each enemy in the list
108 self.enemy_list.on_update(delta_time)
109
110 # Get rid of the bullet when it flies off-screen
111 for bullet in self.bullet_list:
112 if bullet.top < 0:
113 bullet.remove_from_sprite_lists()
114
115 self.bullet_list.update()
116
117 def on_mouse_motion(self, x, y, delta_x, delta_y):
118 """
119 Called whenever the mouse moves.
120 """
121 self.player.center_x = x
122 self.player.center_y = 20
123
124
125def main():
126 """ Run the game """
127 window = MyGame()
128 window.setup()
129 arcade.run()
130
131
132if __name__ == "__main__":
133 main()