forked from Priyansh61/Space-Fighters
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
327 lines (259 loc) · 9.96 KB
/
main.py
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
import pygame
import os
# import time
import random
import sys
# pygame.font.init()
# Instead of initialising the fonts, it's better to initialise pygame directly:
pygame.init()
# Width, height of the playing window
WIDTH, HEIGHT = 720, 670
# Set the display of pygame:
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space Fighters")
# Loading images:
# Menu
MENU_path = os.path.join(os.path.abspath(__file__), "../assets/menu.png")
MENU = pygame.image.load(MENU_path)
# 1. Player Ships
PLAYER_SHIP_1_path = os.path.join(os.path.abspath(__file__), "../assets/player_ship.png")
PLAYER_SHIP_1 = pygame.image.load(PLAYER_SHIP_1_path)
# 2. Enemy Ships
ENEMY_SHIP_1_path = os.path.join(os.path.abspath(__file__), "../assets/red_enemy.png")
ENEMY_SHIP_1 = pygame.image.load(ENEMY_SHIP_1_path)
# 3. Lasers
BLUE_LASERS_path = os.path.join(os.path.abspath(__file__), "../assets/blue_laser.png")
BLUE_LASERS = pygame.image.load(BLUE_LASERS_path)
# 4. Background
BG_1_path = os.path.join(os.path.abspath(__file__), "../assets/space_bg.png")
BG_1 = pygame.image.load(BG_1_path)
# Setting the path like this makes sure the file is found despite where main.py
# is called from.
# Making object classes:
class Laser:
def __init__(self, x, y, img):
self.x = x
self.y = y
self.img = img
self.mask = pygame.mask.from_surface(self.img)
def draw(self, window):
window.blit(self.img, (self.x, self.y))
def move(self, vel):
self.y -= vel
def off_screen(self, height):
return self.y > height or self.y < 0
def collision(self, obj):
return collide(self, obj)
class Ship:
# Initialising object parameters:
def __init__(self, x, y, health=100):
self.x = x
self.y = y
self.health = health
self.ship_img = None
self.laser_img = None
self.lasers = []
self.cooldown_counter = 0
self.COOLDOWN = 40
self.cnt = 0
# Draw for the Ship:
def draw(self, window):
window.blit(self.ship_img, (self.x, self.y))
for laser in self.lasers:
laser.draw(window)
# To provide an interval between lasers:
def cooldown(self):
if self.cooldown_counter >= self.COOLDOWN:
self.cooldown_counter = 0
elif self.cooldown_counter > 0:
self.cooldown_counter += 1
def get_width(self):
return self.ship_img.get_width()
def get_height(self):
return self.ship_img.get_height()
class Player(Ship):
def __init__(self, x, y, health=100):
super().__init__(x, y, health)
self.ship_img = PLAYER_SHIP_1
self.laser_img = BLUE_LASERS
self.mask = pygame.mask.from_surface(self.ship_img)
self.max_health = health
def shoot(self):
self.cooldown()
if self.cooldown_counter == 0:
laser = Laser(self.x, self.y, self.laser_img)
self.lasers.append(laser)
self.cooldown_counter = 1
def move_laser(self, objs, vel):
for laser in self.lasers:
laser.move(vel)
if laser.off_screen(HEIGHT):
self.lasers.remove(laser)
else:
for obj in objs:
if laser.collision(obj):
objs.remove(obj)
if laser in self.lasers:
self.lasers.remove(laser)
def draw(self, window):
super().draw(window)
self.health_bar(window)
def health_bar(self, win):
"""pygame.draw.rect(win, (255, 0, 0), (
self.x, self.y + self.ship_img.get_height() + 10,
self.ship_img.get_width(), 10))
pygame.draw.rect(win, (0, 255, 0), (
self.x, self.y + self.ship_img.get_height() + 10,
(self.ship_img.get_width() * (
1 - (self.max_health - self.health) / self.max_health)), 10))"""
# Simplifying a little:
pos = (self.x, self.y + self.get_height() + 10)
pygame.draw.rect(win, "red", (pos, (self.ship_img.get_width(), 10)))
relative_health = self.health / self.max_health
pygame.draw.rect(win, "green", (pos, (self.get_width() * relative_health, 10)))
# Enemy Ship
class Enemy(Ship):
def __init__(self, x, y, level, health=100):
super().__init__(x, y, health)
self.ship_img = ENEMY_SHIP_1
self.laser_img = BLUE_LASERS
self.mask = pygame.mask.from_surface(self.ship_img)
self.level = level # Give level argument some usage
def shoot(self):
self.cooldown()
if self.cooldown_counter == 0:
"""laser = Laser(self.x + self.get_width() / 2 - 5,
self.y + self.get_height(), self.laser_img)"""
# Simplify it:
laser_x = self.x + self.get_width() / 2 - 5
laser_y = self.y + self.get_height()
laser = Laser(laser_x, laser_y, self.laser_img)
self.lasers.append(laser)
self.cooldown_counter = 1
def move(self):
vel = 1
self.y += vel
def move_laser(self, obj, vel):
for laser in self.lasers:
laser.move(vel)
if laser.off_screen(HEIGHT):
self.lasers.remove(laser)
elif laser.collision(obj):
obj.health -= 10
self.lasers.remove(laser)
# Defining collide:
def collide(obj1, obj2):
offset_x = obj2.x - obj1.x
offset_y = obj2.y - obj1.y
return not (obj1.mask.overlap(obj2.mask, (offset_x, offset_y)) is None)
# Changing return statement so that None is not compared using equality operators
# Defining movement:
def move(player):
ship_vel = 5
key_press = pygame.key.get_pressed()
if (key_press[pygame.K_a] or key_press[pygame.K_LEFT]) and (
player.x - ship_vel > 0): # LEFT
player.x -= ship_vel
if (key_press[pygame.K_d] or key_press[pygame.K_RIGHT]) and (
player.x + ship_vel + player.get_width() < WIDTH): # RIGHT
player.x += ship_vel
if (key_press[pygame.K_w] or key_press[pygame.K_UP]) and (
player.y - ship_vel > 0): # UP
player.y -= ship_vel
if (key_press[pygame.K_s] or key_press[pygame.K_DOWN]) and (
player.y + ship_vel + player.get_height() < HEIGHT): # DOWN
player.y += ship_vel
if key_press[pygame.K_SPACE]:
player.shoot()
# Defining main:
def main():
run = True # Checks if the user has stopped the program or not
game_over = False
fps = 70
level = 0
lives = 5
clock = pygame.time.Clock()
main_font = pygame.font.SysFont("comicsans", 40) # Font used for lives and level
lost_font = pygame.font.SysFont('arial', 60)
# Object parameters:
player = Player(WIDTH / 2, HEIGHT - 70)
enemies = []
num_enemies = 5
# Draw object on the game window:
def redraw_window():
WIN.blit(BG_1, (0, 0))
# Lives and Level Display
lives_disp = main_font.render(f"LIVES: {lives}", True, (255, 255, 255))
level_disp = main_font.render(f"LEVEL: {level}", True, (255, 255, 255))
WIN.blit(lives_disp, (10, 10))
WIN.blit(level_disp, (WIDTH - level_disp.get_width() - 10, 10))
# displaying Ship
player.draw(WIN)
# Enemy Ship
for enemy_ship in enemies:
enemy_ship.draw(WIN)
# Game Over
if game_over:
game_over_disp = lost_font.render("Better luck Next Time!!", True, "red")
menu()
# After calling menu() the rest of lines (254-256) do not run. They only run
# if the game is quit, which gives an error because pygame is already quit.
"""WIN.blit(game_over_disp, (WIDTH / 2 - game_over_disp.get_width() / 2,
HEIGHT / 2 - game_over_disp.get_height() / 2))"""
# Simplify it:
game_over_disp_x = (WIDTH - game_over_disp.get_width()) / 2
game_over_disp_y = (HEIGHT - game_over_disp.get_height()) / 2
WIN.blit(game_over_disp, game_over_disp_x, game_over_disp_y)
pygame.display.update()
while run:
clock.tick(fps)
# Checking for lives and health:
if lives == 0 or player.health <= 0:
# game_over = True
pass
# Deploying enemies:
if len(enemies) == 0:
level += 1
num_enemies += 5
for i in range(num_enemies):
enemy = Enemy(random.randrange(100, WIDTH - 200),
random.randrange(-1000, -100), level)
enemies.append(enemy)
print(num_enemies)
# Moving and removing enemies:
for enemy in enemies:
enemy.move()
if random.randrange(0, 2400) == 2:
enemy.shoot()
# If player and enemy collide:
if collide(player, enemy):
player.health -= 25
enemies.remove(enemy)
enemy.move_laser(player, -2)
if enemy.y + enemy.get_height() > HEIGHT:
lives -= 1
enemies.remove(enemy)
# Moving the deployed lasers:
player.move_laser(enemies, 4)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # Only using this stops the program with an error
sys.exit() # Stop execution of the program (without error)
redraw_window()
# Player Movements:
move(player)
def menu():
check = True
while check:
WIN.blit(MENU, (0, 0))
pygame.display.update()
for event in pygame.event.get():
if pygame.key.get_pressed()[pygame.K_p]:
main()
elif event.type == pygame.QUIT or pygame.key.get_pressed()[pygame.K_q]:
check = False
pygame.quit()
sys.exit() # This is not needed if the game is quit from the menu without being
# played, but it is needed to overcome running lines 254-256 that would give an
# error
menu()