-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfinal.py
More file actions
412 lines (354 loc) · 11.2 KB
/
Copy pathfinal.py
File metadata and controls
412 lines (354 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
import pygame, sys, os, random, math
from pygame.locals import *
# Initialize Pygame and mixer for sound
pygame.mixer.pre_init()
pygame.init()
fps = pygame.time.Clock()
# Define colors
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
# Game configuration
WIDTH = 800
HEIGHT = 600
ASTEROID_SPEED = 2
NUM_ASTEROIDS = 5
BULLET_SPEED = 10
SHIP_SPEED = 10
FRICTION = 0.2
LEVEL_UP_SCORE = 100
MAX_LEVEL = 10
# Global variables
time = 0
score = 0
level = 1
lives = 3
game_over = False
paused = False
high_score = 0
# Initialize game window
window = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
pygame.display.set_caption('Asteroids')
# Load images with error handling
def load_image(filename):
try:
return pygame.image.load(os.path.join('images', filename))
except pygame.error as e:
print(f"Error loading image {filename}: {e}")
sys.exit(1)
bg = load_image('bg.jpg')
debris = load_image('debris2_brown.png')
ship_img = load_image('ship.png')
ship_thrusted_img = load_image('ship_thrusted.png')
asteroid = load_image('asteroid.png')
shot = load_image('shot2.png')
explosion = load_image('explosion_blue.png')
# Load sounds with error handling
def load_sound(filename):
try:
return pygame.mixer.Sound(os.path.join('sounds', filename))
except pygame.error as e:
print(f"Error loading sound {filename}: {e}")
return None
missile_sound = load_sound('missile.ogg')
if missile_sound:
missile_sound.set_volume(1)
thruster_sound = load_sound('thrust.ogg')
if thruster_sound:
thruster_sound.set_volume(1)
explosion_sound = load_sound('explosion.ogg')
if explosion_sound:
explosion_sound.set_volume(1)
# Load background music
try:
pygame.mixer.music.load(os.path.join('sounds', 'game.ogg'))
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play(-1) # Loop indefinitely
except pygame.error as e:
print(f"Error loading music: {e}")
# Load high score from file
def load_high_score():
try:
with open('high_score.txt', 'r') as f:
return int(f.read())
except:
return 0
def save_high_score(score):
with open('high_score.txt', 'w') as f:
f.write(str(score))
high_score = load_high_score()
# Ship class
class Ship:
def __init__(self):
self.x = WIDTH / 2 - 50
self.y = HEIGHT / 2 - 50
self.angle = 0
self.speed = 0
self.is_rotating = False
self.is_forward = False
self.direction = 0
def update(self):
if self.is_rotating:
if self.direction == 0:
self.angle -= 10
else:
self.angle += 10
if self.is_forward or self.speed > 0:
self.x += math.cos(math.radians(self.angle)) * self.speed
self.y -= math.sin(math.radians(self.angle)) * self.speed
if not self.is_forward:
self.speed -= FRICTION
# Wrap around screen
if self.x < 0:
self.x = WIDTH
if self.x > WIDTH:
self.x = 0
if self.y < 0:
self.y = HEIGHT
if self.y > HEIGHT:
self.y = 0
def draw(self, canvas):
global ship_img, ship_thrusted_img
if self.is_forward:
canvas.blit(rot_center(ship_thrusted_img, self.angle), (int(self.x), int(self.y)))
else:
canvas.blit(rot_center(ship_img, self.angle), (int(self.x), int(self.y)))
# Asteroid class
class Asteroid:
def __init__(self, x=None, y=None, size=1):
self.size = size
self.x = x if x is not None else random.randint(0, WIDTH)
self.y = y if y is not None else random.randint(0, HEIGHT)
self.angle = random.randint(0, 365)
self.speed = ASTEROID_SPEED + (level - 1) * 0.5
def update(self):
self.x += math.cos(math.radians(self.angle)) * self.speed
self.y -= math.sin(math.radians(self.angle)) * self.speed
# Wrap around screen
if self.x < 0:
self.x = WIDTH
if self.x > WIDTH:
self.x = 0
if self.y < 0:
self.y = HEIGHT
if self.y > HEIGHT:
self.y = 0
def draw(self, canvas):
scaled_asteroid = pygame.transform.scale(asteroid, (int(50 * self.size), int(50 * self.size)))
canvas.blit(rot_center(scaled_asteroid, self.angle), (self.x, self.y))
# Bullet class
class Bullet:
def __init__(self, x, y, angle):
self.x = x
self.y = y
self.angle = angle
self.speed = BULLET_SPEED
def update(self):
self.x += math.cos(math.radians(self.angle)) * self.speed
self.y -= math.sin(math.radians(self.angle)) * self.speed
def draw(self, canvas):
canvas.blit(shot, (self.x, self.y))
# Game objects
ship = Ship()
asteroids = []
bullets = []
# Initialize asteroids
for i in range(NUM_ASTEROIDS):
asteroids.append(Asteroid())
# set variables
ship_x = WIDTH/2 - 50
ship_y = HEIGHT/2 - 50
ship_angle = 0
ship_is_rotating = False
ship_is_forward = False
ship_direction = 0
ship_speed = 0
asteroid_x = [0,0,0,0,0] #random.randint(0,WIDTH)
asteroid_y = [0,0,0,0,0] #random.randint(0,HEIGHT)
asteroid_angle = []
asteroid_speed = 2
no_asteroids = 5
bullet_x = []
bullet_y = []
bullet_angle = []
no_bullets = 0
score = 0
game_over = False
for i in range(0,no_asteroids):
asteroid_x.append( random.randint(0,WIDTH) )
asteroid_y.append( random.randint(0,HEIGHT) )
asteroid_angle.append( random.randint(0,365) )
def rot_center(image, angle):
"""
Rotate a Surface, maintaining position.
"""
if hasattr(image, 'get_rect'):
orig_rect = image.get_rect()
rot_image = pygame.transform.rotate(image, angle)
rot_rect = orig_rect.copy()
rot_rect.center = rot_image.get_rect().center
rot_image = rot_image.subsurface(rot_rect).copy()
return rot_image
else:
return image
def draw(canvas):
"""
Draw the game elements on the canvas.
"""
global time, score, level, lives, high_score
canvas.fill(BLACK)
canvas.blit(bg, (0, 0))
canvas.blit(debris, (time * 0.3, 0))
canvas.blit(debris, (time * 0.3 - WIDTH, 0))
time += 1
# Draw bullets
for bullet in bullets:
bullet.draw(canvas)
# Draw asteroids
for asteroid in asteroids:
asteroid.draw(canvas)
# Draw ship
ship.draw(canvas)
# Draw UI
myfont1 = pygame.font.SysFont("Comic Sans MS", 30)
label1 = myfont1.render(f"Score: {score}", 1, (255, 255, 0))
canvas.blit(label1, (50, 20))
label2 = myfont1.render(f"Level: {level}", 1, (255, 255, 0))
canvas.blit(label2, (50, 60))
label3 = myfont1.render(f"Lives: {lives}", 1, (255, 255, 0))
canvas.blit(label3, (50, 100))
label4 = myfont1.render(f"High Score: {high_score}", 1, (255, 255, 0))
canvas.blit(label4, (50, 140))
# Draw game over message
if game_over:
myfont2 = pygame.font.SysFont("Comic Sans MS", 80)
label2 = myfont2.render("GAME OVER", 1, (255, 255, 255))
canvas.blit(label2, (WIDTH / 2 - 150, HEIGHT / 2 - 40))
myfont3 = pygame.font.SysFont("Comic Sans MS", 40)
label3 = myfont3.render("Press R to restart", 1, (255, 255, 255))
canvas.blit(label3, (WIDTH / 2 - 100, HEIGHT / 2 + 50))
# Draw pause message
if paused:
myfont2 = pygame.font.SysFont("Comic Sans MS", 80)
label2 = myfont2.render("PAUSED", 1, (255, 255, 255))
canvas.blit(label2, (WIDTH / 2 - 100, HEIGHT / 2 - 40))
def handle_input():
"""
Handle user input events and update ship state.
"""
global paused, game_over, lives, score, level
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT:
ship.is_rotating = True
ship.direction = 0
elif event.key == K_LEFT:
ship.is_rotating = True
ship.direction = 1
elif event.key == K_UP:
ship.is_forward = True
ship.speed = SHIP_SPEED
if thruster_sound:
thruster_sound.play()
elif event.key == K_SPACE:
bullets.append(Bullet(ship.x + 50, ship.y + 50, ship.angle))
if missile_sound:
missile_sound.play()
elif event.key == K_p:
paused = not paused
elif event.key == K_r and game_over:
reset_game()
elif event.type == KEYUP:
if event.key in (K_LEFT, K_RIGHT):
ship.is_rotating = False
elif event.key == K_UP:
ship.is_forward = False
if thruster_sound:
thruster_sound.stop()
def reset_game():
"""
Reset the game state for a new game.
"""
global score, level, lives, game_over, asteroids, bullets
score = 0
level = 1
lives = 3
game_over = False
asteroids = []
bullets = []
for i in range(NUM_ASTEROIDS):
asteroids.append(Asteroid())
ship.x = WIDTH / 2 - 50
ship.y = HEIGHT / 2 - 50
ship.angle = 0
ship.speed = 0
def update_screen():
"""
Update the display and control frame rate.
"""
pygame.display.update()
fps.tick(60)
def isCollision(enemyX, enemyY, bulletX, bulletY, dist):
"""
Check if two objects are colliding based on distance.
"""
distance = math.sqrt((enemyX - bulletX) ** 2 + (enemyY - bulletY) ** 2)
return distance < dist
def game_logic():
"""
Update game logic: move bullets, asteroids, check collisions.
"""
global score, level, lives, game_over, high_score
if paused:
return
# Update ship
ship.update()
# Update bullets
for bullet in bullets[:]:
bullet.update()
if bullet.x < 0 or bullet.x > WIDTH or bullet.y < 0 or bullet.y > HEIGHT:
bullets.remove(bullet)
# Update asteroids
for asteroid in asteroids[:]:
asteroid.update()
# Check collision with ship
if isCollision(ship.x, ship.y, asteroid.x, asteroid.y, 27):
lives -= 1
if lives <= 0:
game_over = True
if score > high_score:
high_score = score
save_high_score(high_score)
else:
ship.x = WIDTH / 2 - 50
ship.y = HEIGHT / 2 - 50
ship.angle = 0
ship.speed = 0
# Check bullet-asteroid collisions
for bullet in bullets[:]:
for asteroid in asteroids[:]:
if isCollision(bullet.x, bullet.y, asteroid.x, asteroid.y, 50):
bullets.remove(bullet)
asteroids.remove(asteroid)
if explosion_sound:
explosion_sound.play()
score += 10 * asteroid.size
break
# Level progression
if len(asteroids) == 0:
level += 1
if level > MAX_LEVEL:
level = MAX_LEVEL
for i in range(NUM_ASTEROIDS + level - 1):
asteroids.append(Asteroid())
# asteroids game loop
while True:
draw(window)
handle_input()
if not game_over:
game_logic()
update_screen()