-
Notifications
You must be signed in to change notification settings - Fork 0
/
Main.py
235 lines (206 loc) · 9.73 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
import pygame
import sys
import random
pygame.font.init()
# Lasers
BLUE_LASER = pygame.image.load("assets\\pixel_laser_blue.png")
GREEN_LASER = pygame.image.load("assets\\pixel_laser_green.png")
RED_LASER = pygame.image.load("assets\\pixel_laser_red.png")
YELLOW_LASER = pygame.image.load("assets\\pixel_laser_yellow.png")
# Ships
BLUE_SHIP = pygame.image.load("assets\\pixel_ship_blue_small.png")
GREEN_SHIP = pygame.image.load("assets\\pixel_ship_green_small.png")
RED_SHIP = pygame.image.load("assets\\pixel_ship_red_small.png")
YELLOW_SHIP = pygame.image.load("assets\\pixel_ship_yellow.png")
# Game Basic Setting
main_font = pygame.font.SysFont("comicsans", 25)
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Space Invaders")
bg_image = pygame.image.load("assets\\background-black.png")
bg_image = pygame.transform.scale(bg_image, (600, 600))
clock = pygame.time.Clock()
pygame.init()
class Ship():
def __init__(self, position_x, position_y, width, height, vel, laser_vel):
self.position_x = position_x
self.position_y = position_y
self.width = width
self.height = height
self.vel = vel
self.ship_image = None
self.laser_image = None
self.laser = None
self.laser_vel = laser_vel
def draw(self, surface):
surface.blit(self.ship_image, (self.position_x, self.position_y))
if self.laser is not None:
self.laser.draw(surface)
def shoot(self, spawn):
if self.laser is None:
self.laser = Laser(self.position_x, self.position_y + spawn, self.laser_image, self.laser_vel)
def get_width(self):
return self.ship_image.get_width()
def get_height(self):
return self.ship_image.get_height()
class Player(Ship):
def __init__(self, position_x, position_y, width, height, vel):
super().__init__(position_x, position_y, width, height, vel, -20)
self.ship_image = pygame.transform.scale(YELLOW_SHIP, (self.width, self.height))
self.laser_image = pygame.transform.scale(YELLOW_LASER, (self.width, self.height))
self.mask = pygame.mask.from_surface(self.ship_image)
self.lives = 3
self.score = 0
def handle_keys(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] or key[pygame.K_a] and self.position_x - self.vel > 0:
self.position_x-=self.vel
if key[pygame.K_RIGHT] or key[pygame.K_d] and self.position_x + self.width + self.vel < 600:
self.position_x+=self.vel
if key[pygame.K_SPACE]:
self.shoot(-50)
class Enemy(Ship):
group_direction = "right"
group_colors_map = {
"red": (RED_SHIP, RED_LASER),
"green": (GREEN_SHIP, GREEN_LASER),
"blue": (BLUE_SHIP, BLUE_LASER)
}
def __init__(self, position_x, position_y, width, height, vel, points, color):
super().__init__(position_x, position_y, width, height, vel, 20)
self.points = points
self.ship_image, self.laser_image = self.group_colors_map[color]
self.ship_image = pygame.transform.scale(self.ship_image, (self.width, self.height))
Enemy.group_direction = "right"
# Masks allow us to better check if the objects collide with each other
self.mask = pygame.mask.from_surface(self.ship_image)
def change_position(self):
if Enemy.group_direction=="left":
self.position_x -= self.vel
else:
self.position_x += self.vel
def change_level(self):
if Enemy.group_direction == "left":
self.position_y += 25
else:
self.position_y += 25
class Laser:
def __init__(self, position_x, position_y, image, vel):
self.image = pygame.transform.scale(image, (50, 50))
self.position_x = position_x
self.position_y = position_y
self.mask = pygame.mask.from_surface(self.image)
self.vel = vel
def draw(self, surface):
surface.blit(self.image, (self.position_x, self.position_y))
def move(self):
self.position_y += self.vel
def collision(self, obj):
return collide(obj, self)
def collide(obj1, obj2):
offset_x = obj2.position_x - obj1.position_x
offset_y = obj2.position_y - obj1.position_y
return obj1.mask.overlap(obj2.mask, (offset_x, offset_y)) != None
def get_enemy(position_x, position_y, width, height, vel, points, color):
return Enemy(position_x, position_y, width, height, vel, points, color)
enemy_rows = []
enemy_rows.append([get_enemy(i, 50, 50, 50, 15, 75, "red") for i in range(0, 400, 50)])
enemy_rows.append([get_enemy(i, 100, 50, 50, 15, 50, "green") for i in range(0, 400, 50)])
enemy_rows.append([get_enemy(i, 150, 50, 50, 15, 50, "green") for i in range(0, 400, 50)])
enemy_rows.append([get_enemy(i, 200, 50, 50, 15, 25, "blue") for i in range(0, 400, 50)])
enemy_rows.append([get_enemy(i, 250, 50, 50, 15, 25, "blue") for i in range(0, 400, 50)])
player = Player(300, 500, 50, 50, 5)
MOVE_ENEMY_EVENT = pygame.USEREVENT + 1
MOVE_PLAYER_LASER_EVENT = pygame.USEREVENT + 2
MOVE_ENEMY_LASER_EVENT = pygame.USEREVENT + 3
CREATE_ENEMY_LASER_EVENT = pygame.USEREVENT + 4
pygame.time.set_timer(MOVE_ENEMY_EVENT, 700)
pygame.time.set_timer(MOVE_PLAYER_LASER_EVENT, 60)
pygame.time.set_timer(MOVE_ENEMY_LASER_EVENT, 100)
pygame.time.set_timer(CREATE_ENEMY_LASER_EVENT, 2000)
# Game Loop
run = True
while True:
if run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == CREATE_ENEMY_LASER_EVENT:
try:
random_row = random.choice(enemy_rows)
if len(random_row) != 0:
enemy = random.choice(random_row)
enemy.shoot(50)
except IndexError:
end_game("You Won !!!")
elif event.type == MOVE_ENEMY_EVENT: # Player Event
# Delete an enemy row if it is empty
[enemy_rows.pop(enemy_rows.index(enemies))
for enemies in enemy_rows if len(enemies) == 0]
# update direction of movement
# Double list comprehension to see
# if any enemy touches the right side of window and
# if yes then we change level and directrion of movment
if any(Enemy.group_direction == "right" and
enemy.position_x + enemy.width + enemy.vel>= 600
for enemies in enemy_rows for enemy in enemies):
Enemy.group_direction = "left"
change_enemies_level()
elif any(Enemy.group_direction == "left" and
enemy.position_x <= 0
for enemies in enemy_rows for enemy in enemies):
Enemy.group_direction = "right"
change_enemies_level()
def change_enemies_level():
[enemy.change_level() for enemies in enemy_rows for enemy in enemies]
# move all enemies in the same direction
[enemy.change_position() for enemies in enemy_rows for enemy in enemies]
elif event.type == MOVE_ENEMY_LASER_EVENT:
for enemies in enemy_rows:
for enemy in enemies:
if enemy.laser is not None: # Does Laser exist
if enemy.laser.position_y + enemy.laser.vel <= 600: # If the Laser is out of the Map
if enemy.laser.collision(player) == True: # Does the laser collide with player
player.lives-=1
enemy.laser = None
if enemy.laser is not None:
enemy.laser.move()
else:
enemy.laser = None
elif event.type == MOVE_PLAYER_LASER_EVENT:
if player.laser is not None: # Does Laser exist
if player.laser.position_y + player.laser.vel >= 0: # If the Laser is out of the Map
loop_escape = False
for enemies in enemy_rows:
for enemy in enemies:
if player.laser.collision(enemy) == True: # Does the laser collide with any enemy
player.score += enemy.points
enemies.pop(enemies.index(enemy))
player.laser = None
loop_escape = True
break
if loop_escape:
break
if player.laser is not None:
player.laser.move()
else:
player.laser = None
screen.blit(bg_image, (0, 0))
def end_game(result):
end_label = main_font.render(result, 1, (255, 255, 255))
screen.blit(end_label, (230,260))
pygame.display.update()
pygame.time.delay(5000)
pygame.quit()
sys.exit()
if player.lives == 0:
end_game("You lost !!!")
lives_label = main_font.render(f"Lives: {player.lives}", 1, (255, 255, 255))
score_label = main_font.render(f"Score: {player.score}", 1, (255, 255, 255))
screen.blit(lives_label, (500, 10))
screen.blit(score_label, (11, 10))
[enemy.draw(screen) for enemies in enemy_rows for enemy in enemies]
player.draw(screen)
player.handle_keys()
pygame.display.update()
clock.tick(50)