1"""
2Sprite Hit Points and Health Bars
3
4Artwork from http://kenney.nl
5
6If Python and Arcade are installed, this example can be run from the command line with:
7python -m arcade.examples.sprite_health
8"""
9import random
10import arcade
11
12SPRITE_SCALING_PLAYER = 0.5
13SPRITE_SCALING_COIN = 0.2
14SPRITE_SCALING_LASER = 0.8
15COIN_COUNT = 50
16
17SCREEN_WIDTH = 800
18SCREEN_HEIGHT = 600
19SCREEN_TITLE = "Hit Points and Health Bars "
20
21BULLET_SPEED = 5
22
23HEALTHBAR_WIDTH = 25
24HEALTHBAR_HEIGHT = 3
25HEALTHBAR_OFFSET_Y = -10
26
27HEALTH_NUMBER_OFFSET_X = -10
28HEALTH_NUMBER_OFFSET_Y = -25
29
30
31class SpriteWithHealth(arcade.Sprite):
32 """ Sprite with hit points """
33
34 def __init__(self, image, scale, max_health):
35 super().__init__(image, scale)
36
37 # Add extra attributes for health
38 self.max_health = max_health
39 self.cur_health = max_health
40
41 def draw_health_number(self):
42 """ Draw how many hit points we have """
43
44 health_string = f"{self.cur_health}/{self.max_health}"
45 arcade.draw_text(health_string,
46 start_x=self.center_x + HEALTH_NUMBER_OFFSET_X,
47 start_y=self.center_y + HEALTH_NUMBER_OFFSET_Y,
48 font_size=12,
49 color=arcade.color.WHITE)
50
51 def draw_health_bar(self):
52 """ Draw the health bar """
53
54 # Draw the 'unhealthy' background
55 if self.cur_health < self.max_health:
56 arcade.draw_rectangle_filled(center_x=self.center_x,
57 center_y=self.center_y + HEALTHBAR_OFFSET_Y,
58 width=HEALTHBAR_WIDTH,
59 height=3,
60 color=arcade.color.RED)
61
62 # Calculate width based on health
63 health_width = HEALTHBAR_WIDTH * (self.cur_health / self.max_health)
64
65 arcade.draw_rectangle_filled(center_x=self.center_x - 0.5 * (HEALTHBAR_WIDTH - health_width),
66 center_y=self.center_y - 10,
67 width=health_width,
68 height=HEALTHBAR_HEIGHT,
69 color=arcade.color.GREEN)
70
71class MyGame(arcade.Window):
72 """ Main application class. """
73
74 def __init__(self):
75 """ Initializer """
76 # Call the parent class initializer
77 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
78
79 # Variables that will hold sprite lists
80 self.player_list = None
81 self.coin_list = None
82 self.bullet_list = None
83
84 # Set up the player info
85 self.player_sprite = None
86 self.score = 0
87
88 # Don't show the mouse cursor
89 self.set_mouse_visible(False)
90
91 # Load sounds. Sounds from kenney.nl
92 self.gun_sound = arcade.load_sound(":resources:sounds/hurt5.wav")
93 self.hit_sound = arcade.load_sound(":resources:sounds/hit4.wav")
94 self.death_sound = arcade.load_sound(":resources:sounds/hit5.wav")
95
96 arcade.set_background_color(arcade.color.AMAZON)
97
98 def setup(self):
99
100 """ Set up the game and initialize the variables. """
101
102 # Sprite lists
103 self.player_list = arcade.SpriteList()
104 self.coin_list = arcade.SpriteList()
105 self.bullet_list = arcade.SpriteList()
106
107 # Set up the player
108 self.score = 0
109
110 # Image from kenney.nl
111 self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING_PLAYER)
112 self.player_sprite.center_x = 50
113 self.player_sprite.center_y = 70
114 self.player_list.append(self.player_sprite)
115
116 # Create the coins
117 for i in range(COIN_COUNT):
118
119 # Create the coin instance
120 # Coin image from kenney.nl
121 coin = SpriteWithHealth(":resources:images/items/coinGold.png",
122 SPRITE_SCALING_COIN,
123 max_health=5)
124
125 # Position the coin
126 coin.center_x = random.randrange(SCREEN_WIDTH)
127 coin.center_y = random.randrange(150, SCREEN_HEIGHT)
128
129 # Add the coin to the lists
130 self.coin_list.append(coin)
131
132 # Set the background color
133 arcade.set_background_color(arcade.color.AMAZON)
134
135 def on_draw(self):
136 """
137 Render the screen.
138 """
139
140 # This command has to happen before we start drawing
141 arcade.start_render()
142
143 # Draw all the sprites.
144 self.coin_list.draw()
145 self.bullet_list.draw()
146 self.player_list.draw()
147
148 for coin in self.coin_list:
149 coin.draw_health_number()
150 coin.draw_health_bar()
151
152 # Render the text
153 arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE, 14)
154
155 def on_mouse_motion(self, x, y, dx, dy):
156 """
157 Called whenever the mouse moves.
158 """
159 self.player_sprite.center_x = x
160
161 def on_mouse_press(self, x, y, button, modifiers):
162 """
163 Called whenever the mouse button is clicked.
164 """
165 # Gunshot sound
166 arcade.play_sound(self.gun_sound)
167 # Create a bullet
168 bullet = arcade.Sprite(":resources:images/space_shooter/laserBlue01.png", SPRITE_SCALING_LASER)
169
170 # The image points to the right, and we want it to point up. So
171 # rotate it.
172 bullet.angle = 90
173
174 # Give the bullet a speed
175 bullet.change_y = BULLET_SPEED
176
177 # Position the bullet
178 bullet.center_x = self.player_sprite.center_x
179 bullet.bottom = self.player_sprite.top
180
181 # Add the bullet to the appropriate lists
182 self.bullet_list.append(bullet)
183
184 def on_update(self, delta_time):
185 """ Movement and game logic """
186
187 # Call update on bullet sprites
188 self.bullet_list.update()
189
190 # Loop through each bullet
191 for bullet in self.bullet_list:
192
193 # Check this bullet to see if it hit a coin
194 hit_list = arcade.check_for_collision_with_list(bullet, self.coin_list)
195
196 # If it did, get rid of the bullet
197 if len(hit_list) > 0:
198 bullet.remove_from_sprite_lists()
199
200 # For every coin we hit, process
201 for coin in hit_list:
202 # Make sure this is the right type of class
203 if not isinstance(coin, SpriteWithHealth):
204 raise TypeError("List contents must be all ints")
205
206 # Remove one health point
207 coin.cur_health -= 1
208
209 # Check health
210 if coin.cur_health <= 0:
211 # Dead
212 coin.remove_from_sprite_lists()
213 self.score += 1
214 arcade.play_sound(self.death_sound)
215 else:
216 # Not dead
217 arcade.play_sound(self.hit_sound)
218
219 # If the bullet flies off-screen, remove it.
220 if bullet.bottom > SCREEN_HEIGHT:
221 bullet.remove_from_sprite_lists()
222
223
224def main():
225 """ Main Program """
226 window = MyGame()
227 window.setup()
228 arcade.run()
229
230
231if __name__ == "__main__":
232 main()