awacke1 commited on
Commit
d8aa43c
·
verified ·
1 Parent(s): 6fe12f2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +426 -0
app.py ADDED
@@ -0,0 +1,426 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Asteroid Smasher
3
+
4
+ Shoot space rocks in this demo program created with
5
+ Python and the Arcade library.
6
+
7
+ Artwork from https://kenney.nl
8
+
9
+ If Python and Arcade are installed, this example can be run from the command line with:
10
+ python -m arcade.examples.asteroid_smasher
11
+ """
12
+ import random
13
+ import math
14
+ import arcade
15
+
16
+ from typing import cast
17
+
18
+ STARTING_ASTEROID_COUNT = 3
19
+ SCALE = 0.5
20
+ OFFSCREEN_SPACE = 300
21
+ SCREEN_WIDTH = 800
22
+ SCREEN_HEIGHT = 600
23
+ SCREEN_TITLE = "Asteroid Smasher"
24
+ LEFT_LIMIT = -OFFSCREEN_SPACE
25
+ RIGHT_LIMIT = SCREEN_WIDTH + OFFSCREEN_SPACE
26
+ BOTTOM_LIMIT = -OFFSCREEN_SPACE
27
+ TOP_LIMIT = SCREEN_HEIGHT + OFFSCREEN_SPACE
28
+
29
+
30
+ class TurningSprite(arcade.Sprite):
31
+ """ Sprite that sets its angle to the direction it is traveling in. """
32
+ def update(self):
33
+ """ Move the sprite """
34
+ super().update()
35
+ self.angle = math.degrees(math.atan2(self.change_y, self.change_x))
36
+
37
+
38
+ class ShipSprite(arcade.Sprite):
39
+ """
40
+ Sprite that represents our space ship.
41
+
42
+ Derives from arcade.Sprite.
43
+ """
44
+ def __init__(self, filename, scale):
45
+ """ Set up the space ship. """
46
+
47
+ # Call the parent Sprite constructor
48
+ super().__init__(filename, scale)
49
+
50
+ # Info on where we are going.
51
+ # Angle comes in automatically from the parent class.
52
+ self.thrust = 0
53
+ self.speed = 0
54
+ self.max_speed = 4
55
+ self.drag = 0.05
56
+ self.respawning = 0
57
+
58
+ # Mark that we are respawning.
59
+ self.respawn()
60
+
61
+ def respawn(self):
62
+ """
63
+ Called when we die and need to make a new ship.
64
+ 'respawning' is an invulnerability timer.
65
+ """
66
+ # If we are in the middle of respawning, this is non-zero.
67
+ self.respawning = 1
68
+ self.center_x = SCREEN_WIDTH / 2
69
+ self.center_y = SCREEN_HEIGHT / 2
70
+ self.angle = 0
71
+
72
+ def update(self):
73
+ """
74
+ Update our position and other particulars.
75
+ """
76
+ if self.respawning:
77
+ self.respawning += 1
78
+ self.alpha = self.respawning
79
+ if self.respawning > 250:
80
+ self.respawning = 0
81
+ self.alpha = 255
82
+ if self.speed > 0:
83
+ self.speed -= self.drag
84
+ if self.speed < 0:
85
+ self.speed = 0
86
+
87
+ if self.speed < 0:
88
+ self.speed += self.drag
89
+ if self.speed > 0:
90
+ self.speed = 0
91
+
92
+ self.speed += self.thrust
93
+ if self.speed > self.max_speed:
94
+ self.speed = self.max_speed
95
+ if self.speed < -self.max_speed:
96
+ self.speed = -self.max_speed
97
+
98
+ self.change_x = -math.sin(math.radians(self.angle)) * self.speed
99
+ self.change_y = math.cos(math.radians(self.angle)) * self.speed
100
+
101
+ self.center_x += self.change_x
102
+ self.center_y += self.change_y
103
+
104
+ # If the ship goes off-screen, move it to the other side of the window
105
+ if self.right < 0:
106
+ self.left = SCREEN_WIDTH
107
+
108
+ if self.left > SCREEN_WIDTH:
109
+ self.right = 0
110
+
111
+ if self.bottom < 0:
112
+ self.top = SCREEN_HEIGHT
113
+
114
+ if self.top > SCREEN_HEIGHT:
115
+ self.bottom = 0
116
+
117
+ """ Call the parent class. """
118
+ super().update()
119
+
120
+
121
+ class AsteroidSprite(arcade.Sprite):
122
+ """ Sprite that represents an asteroid. """
123
+
124
+ def __init__(self, image_file_name, scale):
125
+ super().__init__(image_file_name, scale=scale)
126
+ self.size = 0
127
+
128
+ def update(self):
129
+ """ Move the asteroid around. """
130
+ super().update()
131
+ if self.center_x < LEFT_LIMIT:
132
+ self.center_x = RIGHT_LIMIT
133
+ if self.center_x > RIGHT_LIMIT:
134
+ self.center_x = LEFT_LIMIT
135
+ if self.center_y > TOP_LIMIT:
136
+ self.center_y = BOTTOM_LIMIT
137
+ if self.center_y < BOTTOM_LIMIT:
138
+ self.center_y = TOP_LIMIT
139
+
140
+
141
+ class MyGame(arcade.Window):
142
+ """ Main application class. """
143
+
144
+ def __init__(self):
145
+ super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
146
+
147
+ self.game_over = False
148
+
149
+ # Sprite lists
150
+ self.player_sprite_list = arcade.SpriteList()
151
+ self.asteroid_list = arcade.SpriteList()
152
+ self.bullet_list = arcade.SpriteList()
153
+ self.ship_life_list = arcade.SpriteList()
154
+
155
+ # Set up the player
156
+ self.score = 0
157
+ self.player_sprite = None
158
+ self.lives = 3
159
+
160
+ # Sounds
161
+ self.laser_sound = arcade.load_sound(":resources:sounds/hurt5.wav")
162
+ self.hit_sound1 = arcade.load_sound(":resources:sounds/explosion1.wav")
163
+ self.hit_sound2 = arcade.load_sound(":resources:sounds/explosion2.wav")
164
+ self.hit_sound3 = arcade.load_sound(":resources:sounds/hit1.wav")
165
+ self.hit_sound4 = arcade.load_sound(":resources:sounds/hit2.wav")
166
+
167
+ # Text
168
+ self.text_score = None
169
+ self.text_asteroid_count = None
170
+
171
+ def start_new_game(self):
172
+ """ Set up the game and initialize the variables. """
173
+
174
+ self.game_over = False
175
+
176
+ # Sprite lists
177
+ self.player_sprite_list = arcade.SpriteList()
178
+ self.asteroid_list = arcade.SpriteList()
179
+ self.bullet_list = arcade.SpriteList()
180
+ self.ship_life_list = arcade.SpriteList()
181
+
182
+ # Set up the player
183
+ self.score = 0
184
+ self.player_sprite = ShipSprite(":resources:images/space_shooter/"
185
+ "playerShip1_orange.png",
186
+ SCALE)
187
+ self.player_sprite_list.append(self.player_sprite)
188
+ self.lives = 3
189
+
190
+ # Set up the little icons that represent the player lives.
191
+ cur_pos = 10
192
+ for i in range(self.lives):
193
+ life = arcade.Sprite(":resources:images/space_shooter/"
194
+ "playerLife1_orange.png",
195
+ SCALE)
196
+ life.center_x = cur_pos + life.width
197
+ life.center_y = life.height
198
+ cur_pos += life.width
199
+ self.ship_life_list.append(life)
200
+
201
+ # Make the asteroids
202
+ image_list = (":resources:images/space_shooter/meteorGrey_big1.png",
203
+ ":resources:images/space_shooter/meteorGrey_big2.png",
204
+ ":resources:images/space_shooter/meteorGrey_big3.png",
205
+ ":resources:images/space_shooter/meteorGrey_big4.png")
206
+ for i in range(STARTING_ASTEROID_COUNT):
207
+ image_no = random.randrange(4)
208
+ enemy_sprite = AsteroidSprite(image_list[image_no], SCALE)
209
+ enemy_sprite.guid = "Asteroid"
210
+
211
+ enemy_sprite.center_y = random.randrange(BOTTOM_LIMIT, TOP_LIMIT)
212
+ enemy_sprite.center_x = random.randrange(LEFT_LIMIT, RIGHT_LIMIT)
213
+
214
+ enemy_sprite.change_x = random.random() * 2 - 1
215
+ enemy_sprite.change_y = random.random() * 2 - 1
216
+
217
+ enemy_sprite.change_angle = (random.random() - 0.5) * 2
218
+ enemy_sprite.size = 4
219
+ self.asteroid_list.append(enemy_sprite)
220
+
221
+ # Create new text objects with initial values
222
+ self.text_score = arcade.Text(
223
+ f"Score: {self.score}",
224
+ start_x=10,
225
+ start_y=70,
226
+ font_size=13,
227
+ )
228
+ self.text_asteroid_count = arcade.Text(
229
+ f"Asteroid Count: {len(self.asteroid_list)}",
230
+ start_x=10,
231
+ start_y=50,
232
+ font_size=13,
233
+ )
234
+
235
+ def on_draw(self):
236
+ """
237
+ Render the screen.
238
+ """
239
+
240
+ # This command has to happen before we start drawing
241
+ self.clear()
242
+
243
+ # Draw all the sprites.
244
+ self.asteroid_list.draw()
245
+ self.ship_life_list.draw()
246
+ self.bullet_list.draw()
247
+ self.player_sprite_list.draw()
248
+
249
+ # Draw the text
250
+ self.text_score.draw()
251
+ self.text_asteroid_count.draw()
252
+
253
+ def on_key_press(self, symbol, modifiers):
254
+ """ Called whenever a key is pressed. """
255
+ # Shoot if the player hit the space bar and we aren't respawning.
256
+ if not self.player_sprite.respawning and symbol == arcade.key.SPACE:
257
+ bullet_sprite = TurningSprite(":resources:images/space_shooter/"
258
+ "laserBlue01.png",
259
+ SCALE)
260
+ bullet_sprite.guid = "Bullet"
261
+
262
+ bullet_speed = 13
263
+ bullet_sprite.change_y = \
264
+ math.cos(math.radians(self.player_sprite.angle)) * bullet_speed
265
+ bullet_sprite.change_x = \
266
+ -math.sin(math.radians(self.player_sprite.angle)) \
267
+ * bullet_speed
268
+
269
+ bullet_sprite.center_x = self.player_sprite.center_x
270
+ bullet_sprite.center_y = self.player_sprite.center_y
271
+ bullet_sprite.update()
272
+
273
+ self.bullet_list.append(bullet_sprite)
274
+
275
+ arcade.play_sound(self.laser_sound, speed=random.random() * 3 + 0.5)
276
+
277
+ if symbol == arcade.key.LEFT:
278
+ self.player_sprite.change_angle = 3
279
+ elif symbol == arcade.key.RIGHT:
280
+ self.player_sprite.change_angle = -3
281
+ elif symbol == arcade.key.UP:
282
+ self.player_sprite.thrust = 0.15
283
+ elif symbol == arcade.key.DOWN:
284
+ self.player_sprite.thrust = -.2
285
+
286
+ def on_key_release(self, symbol, modifiers):
287
+ """ Called whenever a key is released. """
288
+ if symbol == arcade.key.LEFT:
289
+ self.player_sprite.change_angle = 0
290
+ elif symbol == arcade.key.RIGHT:
291
+ self.player_sprite.change_angle = 0
292
+ elif symbol == arcade.key.UP:
293
+ self.player_sprite.thrust = 0
294
+ elif symbol == arcade.key.DOWN:
295
+ self.player_sprite.thrust = 0
296
+
297
+ def split_asteroid(self, asteroid: AsteroidSprite):
298
+ """ Split an asteroid into chunks. """
299
+ x = asteroid.center_x
300
+ y = asteroid.center_y
301
+ self.score += 1
302
+
303
+ if asteroid.size == 4:
304
+ for i in range(3):
305
+ image_no = random.randrange(2)
306
+ image_list = [":resources:images/space_shooter/meteorGrey_med1.png",
307
+ ":resources:images/space_shooter/meteorGrey_med2.png"]
308
+
309
+ enemy_sprite = AsteroidSprite(image_list[image_no],
310
+ SCALE * 1.5)
311
+
312
+ enemy_sprite.center_y = y
313
+ enemy_sprite.center_x = x
314
+
315
+ enemy_sprite.change_x = random.random() * 2.5 - 1.25
316
+ enemy_sprite.change_y = random.random() * 2.5 - 1.25
317
+
318
+ enemy_sprite.change_angle = (random.random() - 0.5) * 2
319
+ enemy_sprite.size = 3
320
+
321
+ self.asteroid_list.append(enemy_sprite)
322
+ self.hit_sound1.play()
323
+
324
+ elif asteroid.size == 3:
325
+ for i in range(3):
326
+ image_no = random.randrange(2)
327
+ image_list = [":resources:images/space_shooter/meteorGrey_small1.png",
328
+ ":resources:images/space_shooter/meteorGrey_small2.png"]
329
+
330
+ enemy_sprite = AsteroidSprite(image_list[image_no],
331
+ SCALE * 1.5)
332
+
333
+ enemy_sprite.center_y = y
334
+ enemy_sprite.center_x = x
335
+
336
+ enemy_sprite.change_x = random.random() * 3 - 1.5
337
+ enemy_sprite.change_y = random.random() * 3 - 1.5
338
+
339
+ enemy_sprite.change_angle = (random.random() - 0.5) * 2
340
+ enemy_sprite.size = 2
341
+
342
+ self.asteroid_list.append(enemy_sprite)
343
+ self.hit_sound2.play()
344
+
345
+ elif asteroid.size == 2:
346
+ for i in range(3):
347
+ image_no = random.randrange(2)
348
+ image_list = [":resources:images/space_shooter/meteorGrey_tiny1.png",
349
+ ":resources:images/space_shooter/meteorGrey_tiny2.png"]
350
+
351
+ enemy_sprite = AsteroidSprite(image_list[image_no],
352
+ SCALE * 1.5)
353
+
354
+ enemy_sprite.center_y = y
355
+ enemy_sprite.center_x = x
356
+
357
+ enemy_sprite.change_x = random.random() * 3.5 - 1.75
358
+ enemy_sprite.change_y = random.random() * 3.5 - 1.75
359
+
360
+ enemy_sprite.change_angle = (random.random() - 0.5) * 2
361
+ enemy_sprite.size = 1
362
+
363
+ self.asteroid_list.append(enemy_sprite)
364
+ self.hit_sound3.play()
365
+
366
+ elif asteroid.size == 1:
367
+ self.hit_sound4.play()
368
+
369
+ def on_update(self, x):
370
+ """ Move everything """
371
+
372
+ if not self.game_over:
373
+ self.asteroid_list.update()
374
+ self.bullet_list.update()
375
+ self.player_sprite_list.update()
376
+
377
+ for bullet in self.bullet_list:
378
+ asteroids = arcade.check_for_collision_with_list(bullet,
379
+ self.asteroid_list)
380
+
381
+ for asteroid in asteroids:
382
+ # expected AsteroidSprite, got Sprite instead
383
+ self.split_asteroid(cast(AsteroidSprite, asteroid))
384
+ asteroid.remove_from_sprite_lists()
385
+ bullet.remove_from_sprite_lists()
386
+
387
+ # Remove bullet if it goes off-screen
388
+ size = max(bullet.width, bullet.height)
389
+ if bullet.center_x < 0 - size:
390
+ bullet.remove_from_sprite_lists()
391
+ if bullet.center_x > SCREEN_WIDTH + size:
392
+ bullet.remove_from_sprite_lists()
393
+ if bullet.center_y < 0 - size:
394
+ bullet.remove_from_sprite_lists()
395
+ if bullet.center_y > SCREEN_HEIGHT + size:
396
+ bullet.remove_from_sprite_lists()
397
+
398
+ if not self.player_sprite.respawning:
399
+ asteroids = arcade.check_for_collision_with_list(self.player_sprite,
400
+ self.asteroid_list)
401
+ if len(asteroids) > 0:
402
+ if self.lives > 0:
403
+ self.lives -= 1
404
+ self.player_sprite.respawn()
405
+ self.split_asteroid(cast(AsteroidSprite, asteroids[0]))
406
+ asteroids[0].remove_from_sprite_lists()
407
+ self.ship_life_list.pop().remove_from_sprite_lists()
408
+ print("Crash")
409
+ else:
410
+ self.game_over = True
411
+ print("Game over")
412
+
413
+ # Update the text objects
414
+ self.text_score.text = f"Score: {self.score}"
415
+ self.text_asteroid_count.text = f"Asteroid Count: {len(self.asteroid_list)}"
416
+
417
+
418
+ def main():
419
+ """ Start the game """
420
+ window = MyGame()
421
+ window.start_new_game()
422
+ arcade.run()
423
+
424
+
425
+ if __name__ == "__main__":
426
+ main()