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