-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
345 lines (311 loc) · 19.9 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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
import os.path
import random
import pygame
import math
import time
import objects, interface #Import des modules contenant les classes que l'on va instancier
pygame.init()
class Game: # La partie
def __init__(self, app):
self.son_tir_laser = pygame.mixer.Sound(os.path.join(app.folder,"Assets/asteroids-ship-shoot.wav"))
self.son_tir_ennemy = pygame.mixer.Sound(os.path.join(app.folder,"Assets/fire.wav"))
self.son_gameover = pygame.mixer.Sound(os.path.join(app.folder,"Assets/boom.wav"))
self.son_dmg = pygame.mixer.Sound(os.path.join(app.folder,"Assets/beep-03.wav"))
self.son_teleport = pygame.mixer.Sound(os.path.join(app.folder, "Assets/teleport.wav"))
self.app=app
self.score = 0
self.level = 1
self.game_info = interface.GameInfo(self.app)
self.key_pressed = {}
self.player_space_ship = objects.PlayerSpaceShip(self.app.sprites_list, self.app.window_size[0]/2, self.app.window_size[1]/2)
self.coins = 0
self.ennemy_number = 0
self.difficulty=app.settings_list["Difficulty"]
self.start_level(self.level)
def start_level(self, level): # On instancie les objets au début de niveau
self.asteroids = [] # Création d'un tableau qui contient tous les astéroides
self.ennemyspaceships = [] #Création d'un tableau contenant tous les vaisseaux ennemis
self.shots = [] # Création d'un tableau contenant tout les tirs
self.bonus_list = [] #Création d'un tableau contenant les bonus apparus
self.black_hole = [] #Création d'un tableau contenant les trous noirs
for i in range(level+3):
alt_spr = random.randint(1,3)
self.asteroids.append(objects.Asteroid(self.app.sprites_list["Asteroid"+str(alt_spr)], self.app.window_size, 1)) # Instanciation des objets asteroids
if self.level > 1 :
if self.ennemy_number == 0:
self.ennemy_number += 1
if self.level % 5 == 0:
self.ennemy_number += 1
self.black_hole_number = 1
else :
self.black_hole_number = 0
for i in range(self.ennemy_number):
if (self.difficulty>=0):
self.ennemyspaceships.append(objects.EnnemySpaceShip(self.app.sprites_list["Ennemy"], 1, 200, 300))
if (self.difficulty>=1):
self.ennemyspaceships.append(objects.EnnemySpaceShip(self.app.sprites_list["Ennemy1"], 2, 200, 300))
if (self.difficulty==2):
self.ennemyspaceships.append(objects.EnnemySpaceShip(self.app.sprites_list["Ennemy"], 1, 200, 300))
if self.black_hole_number == 1:
tmp_x = random.randint(0, 1)
tmp_y = random.randint(0, 1)
if tmp_x == 0:
if tmp_y == 0:
self.black_hole.append( objects.BlackHole(self.app.sprites_list["BlackHole"], random.randint(100, (self.app.window_size[0]/2)-200), random.randint(100, (self.app.window_size[1]/2)-100))) # Instanciation du trou noir
else:
self.black_hole.append( objects.BlackHole(self.app.sprites_list["BlackHole"], random.randint(100, (self.app.window_size[0]/2)-200), random.randint(100, (self.app.window_size[1]/2)+100)))
else :
if tmp_y == 0:
self.black_hole.append( objects.BlackHole(self.app.sprites_list["BlackHole"], random.randint(100, (self.app.window_size[0]/2)+200), random.randint(100, (self.app.window_size[1]/2)-100)))
else:
self.black_hole.append( objects.BlackHole(self.app.sprites_list["BlackHole"], random.randint(100, (self.app.window_size[0]/2)+200), random.randint(100, (self.app.window_size[1]/2)+100)))
def complete_level(self):
self.player_space_ship.x=self.app.window_size[0]/2
self.player_space_ship.y=self.app.window_size[1]/2
self.score += 100
self.shop=interface.Shop(self)
self.level += 1
self.start_level(self.level)
self.player_space_ship.teleported = 0
self.player_space_ship.is_invincible = 120
def update_loop(self,window,window_size):
self.game_draw(window) #Dessiner ce qu'elle contient dans la fenêtre
self.game_events(window_size)#Gestion des évènements de la partie
self.game_collisions()#Gestion des collisions des objets
def game_events(self,window_size): # Gère les évènements de la partie en continu
self.border_wrapping(self.player_space_ship,window_size)
if (len(self.asteroids) == 0 and len(self.ennemyspaceships) == 0): # Si le niveau est fini
self.complete_level()
for asteroid in self.asteroids:
self.border_wrapping(asteroid,window_size)
for ennemy_space_ship in self.ennemyspaceships: # Les vaisseaux ennemis
if (ennemy_space_ship.type==2):
self.border_wrapping(ennemy_space_ship, window_size)
if math.sqrt( ( (ennemy_space_ship.x - self.player_space_ship.x)**2 )+ ( (ennemy_space_ship.y - self.player_space_ship.y )**2) ) < 400:
if time.time() > ennemy_space_ship.last_shot + ennemy_space_ship.shoot_rate:
tir = objects.LaserShot(self.app.sprites_list["LaserShot2"], 2, ennemy_space_ship.x, ennemy_space_ship.y, ennemy_space_ship.angle_orientation) # Instanciation du tir des vaisseaux ennemis
if (self.app.settings_list["Sounds"]):
self.son_tir_ennemy.play()
self.shots.append(tir)
ennemy_space_ship.last_shot = time.time()
if ennemy_space_ship.life == 0:
self.coins += 20
self.score+=ennemy_space_ship.type*25
self.ennemyspaceships.remove(ennemy_space_ship)
if self.key_pressed.get(pygame.K_LEFT): # Les input
self.player_space_ship.angle_orientation += 5
if self.key_pressed.get(pygame.K_RIGHT):
self.player_space_ship.angle_orientation -= 5
if self.key_pressed.get(pygame.K_UP):
self.player_space_ship.thrust = True
self.player_space_ship.angle_inertie = self.player_space_ship.angle_orientation
else:
self.player_space_ship.thrust = False
if self.key_pressed.get(pygame.K_DOWN):
self.player_space_ship.teleport(self.asteroids, self.ennemyspaceships, self.son_teleport, self.black_hole,self.app.settings_list["Sounds"])
if self.key_pressed.get(pygame.K_SPACE):
if time.time() > self.player_space_ship.last_shot + self.player_space_ship.shoot_rate:
tir = objects.LaserShot(self.app.sprites_list["LaserShot"], 1, self.player_space_ship.x, self.player_space_ship.y, self.player_space_ship.angle_orientation)
if (self.app.settings_list["Sounds"]):
self.son_tir_laser.play()
self.shots.append(tir)
self.player_space_ship.last_shot = time.time()
def game_collisions(self):
if (self.player_space_ship.is_invincible==0):
if pygame.sprite.spritecollide(self.player_space_ship, self.asteroids, False, pygame.sprite.collide_mask): # Collision entre le joueur et les astéroids
if (self.app.settings_list["Sounds"]):
self.son_dmg.play()
self.loose_life()
collisions = pygame.sprite.spritecollide(self.player_space_ship, self.shots, False, pygame.sprite.collide_mask) # Collision entre le joueur et les tirs ennemis
for key in collisions:
if (key.type==2): # Type = 1 tir de joueur, 2 tir ennemis
self.shots.remove(key)
if (self.app.settings_list["Sounds"]):
self.son_dmg.play()
self.loose_life()
if pygame.sprite.spritecollide(self.player_space_ship, self.ennemyspaceships, False, pygame.sprite.collide_mask): # Collision entre le joueur et les vaisseaux ennemis
if (self.app.settings_list["Sounds"]):
self.son_dmg.play()
self.loose_life()
if pygame.sprite.spritecollide(self.player_space_ship, self.black_hole, False, pygame.sprite.collide_mask): # Collision entre le joueuer et le trou noir
while self.player_space_ship.life > 0 :
self.player_space_ship.life -= 1
self.loose_life()
for ennemyspaceship in self.ennemyspaceships:
collisions = pygame.sprite.spritecollide(ennemyspaceship, self.shots, False, pygame.sprite.collide_mask) # Collision entre les vaisseaux ennemis et les tirs
for key in collisions:
if (key.type==1):
self.shots.remove(key)
ennemyspaceship.life-=1
for black_hole in self.black_hole:
collisions = pygame.sprite.spritecollide(black_hole, self.shots, False, pygame.sprite.collide_mask) # Collision entre le trou noir et les tirs
for key in collisions:
if key.type == 1:
self.shots.remove(key)
for asteroid in self.asteroids:
collisions = pygame.sprite.spritecollide(asteroid, self.shots, False, pygame.sprite.collide_mask) # Collision entre les astéroids et les tirs
for key in collisions:
if (key.type==1):
self.shots.remove(key)
if (asteroid.type==3):
luck=random.randint(0,10)
if (luck > 3):
if (luck >9):
self.bonus_list.append(objects.BonusItem(self.app.sprites_list["Bonus2"],2,asteroid.x,asteroid.y))
else:
self.bonus_list.append(objects.BonusItem(self.app.sprites_list["Bonus1"],1,asteroid.x,asteroid.y))
if (asteroid.type<3):
alt_spr=random.randint(1,3)
self.asteroids.append(objects.Asteroid(self.app.sprites_list["Asteroid1"], self.app.window_size, asteroid.type+1,asteroid.x+random.randint(10,20),asteroid.y+random.randint(10,20)))
self.asteroids.append(objects.Asteroid(self.app.sprites_list["Asteroid2"], self.app.window_size, asteroid.type+1,asteroid.x-random.randint(10,20),asteroid.y-random.randint(10,20)))
self.score+=asteroid.type*10
self.asteroids.remove(asteroid)
for shot in self.shots:
if (shot.x<0 or shot.x>self.app.window_size[0] or shot.y<0 or shot.y>self.app.window_size[1]): # Suppression des tirs si ils sortent de l'écran (optimisation)
self.shots.remove(shot)
collisionbonus = pygame.sprite.spritecollide(self.player_space_ship, self.bonus_list, False, pygame.sprite.collide_mask) # Collision entre le joueur et les items bonus
for key in collisionbonus:
if (key.bonus_type==1):
self.coins+=5
elif (key.bonus_type==2):
self.player_space_ship.life+=1
self.bonus_list.remove(key)
for black_hole in self.black_hole:
collisionbonus_trou_noir = pygame.sprite.spritecollide(black_hole, self.bonus_list, False, pygame.sprite.collide_mask) # Collision entre les items et le trou noir
for key in collisionbonus_trou_noir:
self.bonus_list.remove(key)
def border_wrapping(self,obj,window_size): #Si les objets sont à la limite de la fenêtre, ils se tp à l'opposé
if (obj.x > window_size[0]):
obj.x = 0
elif (obj.x < 0 ):
obj.x = window_size[0]
if (obj.y > window_size[1]):
obj.y = 0
elif (obj.y < 0 ):
obj.y = window_size[1]
def loose_life(self):
if self.player_space_ship.life > 1: #Vérifie que le joueur ait + d'une vie
self.player_space_ship.life-=1
self.player_space_ship.get_invincibility(120)
else:
if (self.app.settings_list["Sounds"]):
self.son_gameover.play()
if (self.score>int(self.app.best_list[self.app.settings_list["Player_Name"]])): #Vérifie si le score est un nouveau record personnel
f = open(os.path.join(self.app.folder,"Files/stats.txt"),"w")
for key in self.app.best_list: #Réécrit dans le fichier les scores des différents joueurs
if (key==str(self.app.settings_list["Player_Name"])): #Si c'est le joueur actuel on inscrit le score actuel
f.write(
str(key)+":"+str(self.score)+"\n"
)
else: #Sinon, on réécrit le score stocké auparavant
f.write(
str(key)+":"+str(self.app.best_list[key])+"\n"
)
f.close()
game_over=interface.GameOver(self) #Affiche l'écran de mort
def game_draw(self, win): # Cette fonction va dessiner chaque élément du niveau
for black_hole in self.black_hole:
black_hole.draw(win)
for shot in self.shots:
shot.draw(win)
shot.move()
for bonus in self.bonus_list:
bonus.draw(win)
bonus.move(self.black_hole)
self.player_space_ship.draw(win)
self.player_space_ship.move()
for ennemyspaceship in self.ennemyspaceships:
ennemyspaceship.draw(win)
ennemyspaceship.move(self.player_space_ship)
for asteroid in self.asteroids:
asteroid.draw(win)
asteroid.move()
self.game_info.draw_game_info(self.app,self.score,self.coins,self.level,self.player_space_ship.get_life)
class App: # Le programme
def __init__(self):
self.state="menu"
self.folder = os.path.dirname(__file__)
self.window_size = [1280,720]
pygame.display.set_caption("Asteroids")
self.window = pygame.display.set_mode((self.window_size[0],self.window_size[1]),pygame.DOUBLEBUF)
self.best_list={}
self.settings_list={}
try: # Si le fichier n'est pas présent ou corrompu, on aura une erreur plutôt qu'un plantage
self.load_settings()
self.load_sprites()
self.load_statistics()
except:
print("except") #todo afficher une erreur
self.menu=interface.MainMenu(self)
clock = pygame.time.Clock()
self.running = True
while self.running:
self.window.fill((0,0,0)) # Vide l'affichage de la frame
self.frame_draw() # Appelle la fonction qui dessine les objets du jeu
self.events() # Gestion des évènements/inputs/clics
clock.tick(60) # Met à jour l'affichage
pygame.quit()
def start_game(self):
self.game = Game(self)
self.state="game"
def load_settings(self):
file = open(os.path.join(self.folder,'Files/settings.txt'), 'r') #Charge le fichier de settings
lines = file.readlines()
for line in lines:
if line.strip():
key,value = line.split(":")
self.settings_list[key]=value.strip() # Affecte la valeur à la clé correspondante dans le dictionnaire
self.settings_list["Difficulty"]=int(self.settings_list["Difficulty"])
self.settings_list["Sounds"]=int(self.settings_list["Sounds"])
self.settings_list["Skin_Pack"]=int(self.settings_list["Skin_Pack"])
def load_statistics(self):
file = open(os.path.join(self.folder,'Files/stats.txt'), 'r') #Charge le fichier de stats
lines = file.readlines()
for line in lines:
if line.strip():
key,value = line.split(":")
self.best_list[key]=value.strip() # Affecte la valeur à la clé correspondante dans le dictionnaire
def load_sprites(self): # Va chercher les assets dans les fichiers du jeu
pack=str(self.settings_list["Skin_Pack"])
self.sprites_list = {
"Player": pygame.image.load(os.path.join(self.folder, "Assets/Pack_"+pack+"/player.png")),
"Player1": pygame.image.load(os.path.join(self.folder, "Assets/Pack_"+pack+"/player1.png")),
"LaserShot": pygame.image.load(os.path.join(self.folder, "Assets/laser_shot.png")),
"LaserShot2": pygame.image.load(os.path.join(self.folder, "Assets/laser_shot2.png")),
"Asteroid1": pygame.image.load(os.path.join(self.folder, "Assets/asteroid1.png")),
"Asteroid2": pygame.image.load(os.path.join(self.folder, "Assets/asteroid2.png")),
"Asteroid3": pygame.image.load(os.path.join(self.folder, "Assets/asteroid3.png")),
"Ennemy": pygame.image.load(os.path.join(self.folder, "Assets/Pack_"+pack+"/ennemy.png")),
"Ennemy1": pygame.image.load(os.path.join(self.folder, "Assets/Pack_"+pack+"/ennemy1.png")),
"Bonus1": pygame.image.load(os.path.join(self.folder, "Assets/bonuscoin.png")),
"Bonus2": pygame.image.load(os.path.join(self.folder, "Assets/bonuslife.png")),
"BlackHole" : pygame.image.load(os.path.join(self.folder, "Assets/Black_hole.png")),
"UI_Menu": pygame.image.load(os.path.join(self.folder, "Assets/ui_menu.png")),
"UI_Button": pygame.image.load(os.path.join(self.folder, "Assets/Pack_"+pack+"/ui_button.png")),
"Pack_Banner" : pygame.image.load(os.path.join(self.folder, "Assets/Pack_"+str((self.settings_list["Skin_Pack"]+1)%2)+"/pack_banner.png"))
}
self.title_font = pygame.font.Font(os.path.join(self.folder, 'Assets/title_font.ttf'), 48)
self.text_font = pygame.font.Font(os.path.join(self.folder, 'Assets/text_font.ttf'), 32)
self.button_font = pygame.font.Font(os.path.join(self.folder, 'Assets/text_font.ttf'), 26)
self.mini_font = pygame.font.Font(os.path.join(self.folder, 'Assets/text_font.ttf'), 18)
background=pygame.image.load(os.path.join(self.folder, "Assets/Pack_"+pack+"/background.png"))
self.background=pygame.transform.scale(background, (self.window_size[0], self.window_size[1]))
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT: #Lorsque l'on clique sur la croix pour quitter
self.running = False
if self.state=="game":
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.state="menu"
self.pause=interface.PauseMenu(self)
else:
self.game.key_pressed[event.key] = True
elif event.type == pygame.KEYUP:
self.game.key_pressed[event.key] = False
def frame_draw(self): #Cette fonction va dessiner chaque élément du programme
if self.state=="game":
self.game.update_loop(self.window,self.window_size) #Evènements de la partie à exécuter
pygame.display.update() #Met à jour l'affichage
if __name__ == "__main__": #Instancie le programme
app = App()