#The Maze : Projet ISN réalisé par Bryan A., Martin C. et Isak V., élèves de TS6. import sys, os, time, pygame import tkinter as tk import time from tkinter import filedialog from random import randint # -------- TKINTER -------- # Fenetre pour les sauvegardes/chargement de carte root = tk.Tk() root.withdraw() # -------- PYGAME -------- # Fenetre pour le jeu et ses menus pygame.init() myfont = pygame.font.SysFont("monospace", 50) creditfont = pygame.font.SysFont("monospace", 40, italic=True) # -------- § Variables § -------- # Couleurs BLACK = (0, 0, 0) GRAY = (150, 150, 150) WHITE = (255, 255, 255) # Dossier = "C:/Users/Isak Viste/Documents/Programming/TheMaze/" # Carte de jeu mapSize = 100 Map = [] startPos = (0, 0) # Joueur (position et rotation (statistiques de départ)) x, y = 0, 0 prevRotation = 0 morts = 0 start = 0 end = 0 duree = 0 # Taille et Nom de la fenetre screen = pygame.display.set_mode((700, 700)) temps = 0 # Textures - Terrain rawTextures = ["Ground", "Wall", "Wasteland", "Start", "Goal", "Trap", "Decor"] finTextures = [] imageSize = (0, 0) # Textures - Pieges et Decors xTraps = 3 xDecors = 3 trapTextures = [] decorTextures = [] # Texture - Joueur playerTexture = pygame.image.load(os.path.join("Player.gif")).convert_alpha() playerTexture = pygame.transform.scale(playerTexture, (100, 100)) playerTextureDead = pygame.image.load(os.path.join("PlayerDead.gif")).convert_alpha() playerTextureDead = pygame.transform.scale(playerTextureDead, (100, 100)) # Texture - Banners winBannerTexture = pygame.image.load(os.path.join("WinBanner.jpg")).convert() tryAgainBannerTexture = pygame.image.load(os.path.join("TryAgainBanner.jpg")).convert() # Texture - Boutton butTextures = [] for i in range(6): texture = pygame.image.load(os.path.join('Button' + str(i) + '.gif')).convert_alpha() butTextures.append(pygame.transform.scale(texture, (300, 50))) texture = pygame.image.load(os.path.join('Button' + str(i) + 'i' + '.gif')).convert_alpha() butTextures.append(pygame.transform.scale(texture, (300, 50))) level01Button = pygame.image.load(os.path.join("Level01.gif")).convert_alpha() level01Button = pygame.transform.scale(level01Button, (300, 50)) level01Buttoni = pygame.image.load(os.path.join("Level01i.gif")).convert_alpha() level01Buttoni = pygame.transform.scale(level01Buttoni, (300, 50)) loadButton = pygame.image.load(os.path.join("Load.gif")).convert_alpha() loadButton = pygame.transform.scale(loadButton, (300, 50)) loadButtoni = pygame.image.load(os.path.join("Loadi.gif")).convert_alpha() loadButtoni = pygame.transform.scale(loadButtoni, (300, 50)) # Pygame - Conteur clock = pygame.time.Clock() # -------- MENU PRINCIPAL -------- def MainMenu(): # ------ § Variables § ------ global playerTexture global temps isInMainMenu = True while isInMainMenu: # Nom de la fenetre if(pygame.display.get_caption() != "The Maze | Main Menu"): pygame.display.set_caption("The Maze | Main Menu") # ---- BOUCLE D'EVENEMENT ---- for event in pygame.event.get(): if (event.type == pygame.QUIT): isInMainMenu = False if (event.type == pygame.MOUSEBUTTONUP): # Position de la souris ([0] = x et [1] = y) mp = pygame.mouse.get_pos() if(200 < mp[0] < 500 and 250 < mp[1] < 300): LevelMenu() if(200 < mp[0] < 500 and 350 < mp[1] < 400): if(len(Map) == 0): BlankWorld() LevelEditor() if(200 < mp[0] < 500 and 450 < mp[1] < 500): InstructionsMenu() if(200 < mp[0] < 500 and 550 < mp[1] < 600): isInMainMenu = False # -- EFFACER L'ECRAN -- # Ne pas mettre de commande pour dessiner au dessus! screen.fill(BLACK) Background = pygame.image.load(os.path.join("Background.jpg")).convert_alpha() Background = pygame.transform.scale(Background, (700, 700)) screen.blit(Background,(0,0)) Title = pygame.image.load(os.path.join("Title.gif")).convert_alpha() Title = pygame.transform.scale(Title, (700, 135)) screen.blit(Title,(0,75)) # -- DESSINER SUR L'ECRAN -- # Buttons Button(0, 200, 250, 300, 50) Button(1, 200, 350, 300, 50) Button(4, 200, 450, 300, 50) Button(2, 200, 550, 300, 50) # Credits label = myfont.render("Created by Bryan ARTHAUD, Martin CORSON et Isak VISTE", 1, (200,200,67)) if (700 - temps > -label.get_rect().width): screen.blit(label, (700 - temps, 620)) temps += 10 else: temps = 0 # -- METTRE A JOUR LA FENETRE -- pygame.display.flip() # ---- LIMITER A 60 IMAGES PAR SECONDE ---- clock.tick(60) def Button(id, x, y, length, height): # § Variables § mouse = pygame.mouse.get_pos() if(x+length > mouse[0] > x and y+height > mouse[1] > y): screen.blit(butTextures[id*2+1],(x,y)) else: screen.blit(butTextures[id*2],(x,y)) # -------- MENU NIVEAUX -------- def LevelMenu(): # ------ § Variables § ------ global playerTexture global morts global start level01 = os.path.join("Mazes/Level01.maze") isInLevelMenu = True while isInLevelMenu: # Nom de la fenetre if(pygame.display.get_caption() != "The Maze | Level Menu"): pygame.display.set_caption("The Maze | Level Menu") # ---- BOUCLE D'EVENEMENT ---- for event in pygame.event.get(): if (event.type == pygame.QUIT): isInLevelMenu = False if (event.type == pygame.MOUSEBUTTONUP): # Position de la souris ([0] = x et [1] = y) mp = pygame.mouse.get_pos() if(200 < mp[0] < 500 and 300 < mp[1] < 350): if(len(Map) == 0): BlankWorld() LoadLevel(level01) playerTexture = pygame.transform.rotate(playerTexture, 0) morts = 0 start = pygame.time.get_ticks() PlayGame() isInLevelMenu = False if(200 < mp[0] < 500 and 400 < mp[1] < 450): if(len(Map) == 0): BlankWorld() LoadWorld() playerTexture = pygame.transform.rotate(playerTexture, 0) morts = 0 start = pygame.time.get_ticks() PlayGame() isInLevelMenu = False if(200 < mp[0] < 500 and 500 < mp[1] < 550): isInLevelMenu = False # -- EFFACER L'ECRAN -- # Ne pas mettre de commande pour dessiner au dessus! screen.fill(BLACK) Background = pygame.image.load(os.path.join("Background.jpg")).convert_alpha() Background = pygame.transform.scale(Background, (700, 700)) screen.blit(Background,(0,0)) Title = pygame.image.load(os.path.join("Title.gif")).convert_alpha() Title = pygame.transform.scale(Title, (700, 135)) screen.blit(Title,(0,125)) # -- DESSINER SUR L'ECRAN -- # Buttons mp = pygame.mouse.get_pos() if(200+300 > mp[0] > 200 and 300+50 > mp[1] > 300): screen.blit(level01Buttoni, (200,300)) else: screen.blit(level01Button, (200,300)) if(200+300 > mp[0] > 200 and 400+50 > mp[1] > 400): screen.blit(loadButtoni, (200,400)) else: screen.blit(loadButton, (200,400)) Button(2, 200, 500, 300, 50) # -- METTRE A JOUR LA FENETRE -- pygame.display.flip() # ---- LIMITER A 60 IMAGES PAR SECONDE ---- clock.tick(60) #Menu d'instructions def InstructionsMenu(): isInInstructionsMenu = True page = 1 while isInInstructionsMenu: # Nom de la fenetre if(pygame.display.get_caption() != "The Maze | Instructions"): pygame.display.set_caption("The Maze | Instructions") # ---- BOUCLE D'EVENEMENT ---- for event in pygame.event.get(): if (event.type == pygame.QUIT): isInInstructionsMenu = False if (event.type == pygame.MOUSEBUTTONUP): # Position de la souris ([0] = x et [1] = y) mp = pygame.mouse.get_pos() if(50 < mp[0] < 350 and 625 < mp[1] < 675): isInInstructionsMenu = False #Pour changer de page d'instructions si on clique sur le bouton placé aux coordonnées suivantes. if(350 < mp[0] < 650 and 625 < mp[1] < 675): if page == 1: page = 2 else: page = 1 # -- EFFACER L'ECRAN -- # Ne pas mettre de commande pour dessiner au dessus! screen.fill(BLACK) Background = pygame.image.load(os.path.join("Background.jpg")).convert_alpha() Background = pygame.transform.scale(Background, (700, 700)) screen.blit(Background,(0,0)) Title = pygame.image.load(os.path.join("Title.gif")).convert_alpha() Title = pygame.transform.scale(Title, (700, 135)) screen.blit(Title,(0,35)) #Pour afficher une page d'instructions ou l'autre if page == 2: ParchemInstructions = pygame.image.load(os.path.join("ParchemInstructions2.gif")).convert_alpha() ParchemInstructions = pygame.transform.scale(ParchemInstructions, (700, 413)) screen.blit(ParchemInstructions,(0,200)) else: ParchemInstructions = pygame.image.load(os.path.join("ParchemInstructions1.gif")).convert_alpha() ParchemInstructions = pygame.transform.scale(ParchemInstructions, (700, 413)) screen.blit(ParchemInstructions,(0,200)) # -- DESSINER SUR L'ECRAN -- # Buttons Button(2, 50, 625, 300, 50) Button(5, 350, 625, 300, 50) # -- METTRE A JOUR LA FENETRE -- pygame.display.flip() # ---- LIMITER A 60 IMAGES PAR SECONDE ---- clock.tick(60) # -------- GENERATION DE LA CARTE -------- def BlankWorld(): # ------ § Variables § ------ global Map Map = [] for i in range (mapSize): Map.append([]) for j in range (mapSize): Map[i].append(0) # -------- IMPORTER LES TEXTURES -------- def ImportTextures(imgS): global imageSize imageSize = (imgS, imgS) for val in rawTextures: ImportImage(finTextures, val, "jpg", imageSize, rawTextures.index(val)) for i in range (xTraps): ImportImage(trapTextures, "Trap" + str(i), "jpg", imageSize, i) for i in range (xDecors): ImportImage(decorTextures, "Decor" + str(i), "jpg", imageSize, i) # -------- IMPORTER DES IMAGES -------- def ImportImage(liste, image, ext, size, pos): texture = pygame.image.load(os.path.join(image + '.' + ext)).convert() try: liste[pos] = pygame.transform.scale(texture, size) except: liste.append(pygame.transform.scale(texture, size)) # -------- JEU PRINCIPAL -------- def PlayGame(): pygame.display.set_caption("The Maze | Play") # ------ § Variables § ------ global x, y global prevRotation global playerTexture global morts global imageSize global start global duree global end x, y = startPos # Importer des images ImportTextures(100) # Diversifier les Pieges for i in range (mapSize): for j in range (mapSize): if (Map[i][j] == 5): Map[i][j] = 10 + randint(0, xTraps-1) elif (Map[i][j] == 6): Map[i][j] = 50 + randint(0, xDecors-1) timerActive = True isDead = False gameOver = False isGameOver = True isRunning = True playerMoved = True # ------ BOUCLE PRINCIPAL ------ while isRunning: # ---- BOUCLE D'EVENEMENT ---- for event in pygame.event.get(): if (event.type == pygame.QUIT): isRunning = False if (event.type == pygame.KEYDOWN): if (event.key == pygame.K_UP and playerMoved == False): y = MovePlayer(90, 0, -1, y, -1) playerMoved = True if (event.key == pygame.K_DOWN and playerMoved == False): y = MovePlayer(270, 0, 1, y, 1) playerMoved = True if (event.key == pygame.K_RIGHT and playerMoved == False): x = MovePlayer(0, 1, 0, x, 1) playerMoved = True if (event.key == pygame.K_LEFT and playerMoved == False): x = MovePlayer(180, -1, 0, x, -1) playerMoved = True # ---- LOGIQUE DU JEU ---- # Si le joueur a bougé if (playerMoved == True): # Si le joueur est sur la case de fin if (Map[x][y] == 4): gameOver = True isRunning = False if (Map[x][y] >= 10 and Map[x][y] < 50): isDead = True gameOver = True isRunning = False morts += 1 # -- EFFACER L'ECRAN -- # Ne pas mettre de commande pour dessiner au dessus! screen.fill(BLACK) # -- DESSINER SUR L'ECRAN -- DrawScreen(imageSize, 3, 4) screen.blit(playerTexture, (300, 300)) # -- METTRE A JOUR LA FENETRE -- pygame.display.flip() playerMoved = False # ---- LIMITER A 60 IMAGES PAR SECONDE ---- clock.tick(60) if (gameOver == True): # ------ BOUCLE PRINCIPAL ------ while isGameOver: # ---- BOUCLE D'EVENEMENT ---- for event in pygame.event.get(): if (event.type == pygame.QUIT): isGameOver = False if (event.type == pygame.KEYDOWN): if (event.key == pygame.K_SPACE): isGameOver = False if (isDead == False): morts = 0 start = pygame.time.get_ticks() PlayGame() if (event.type == pygame.MOUSEBUTTONUP): mp = pygame.mouse.get_pos() if(200 < mp[0] < 500 and 500 < mp[1] < 550): isGameOver = False if (isDead == False): morts = 0 start = pygame.time.get_ticks() PlayGame() if(200 < mp[0] < 500 and 600 < mp[1] < 650): isGameOver = False # -- EFFACER L'ECRAN -- # Ne pas mettre de commande pour dessiner au dessus! screen.fill(BLACK) # -- DESSINER SUR L'ECRAN -- DrawScreen(imageSize, 3, 4) if (isDead == True): screen.blit(playerTextureDead, (300, 300)) screen.blit(winBannerTexture, ((700 / 2 - 310, 40))) label = myfont.render("YOU LOSE", 1, (255, 255, 255)) screen.blit(label, (700 / 2 - label.get_rect().width / 2, 50)) end = pygame.time.get_ticks() else: Finishline = pygame.image.load(os.path.join("Finishline.gif")).convert_alpha() screen.blit(Finishline,(0,0)) screen.blit(winBannerTexture, ((700 / 2 - 310, 40))) label = myfont.render("YOU WIN", 1, (255,255,255)) screen.blit(label, (700/2-label.get_rect().width/2, 50)) #Pour arrêter le chronomètre si le joueur a fini le niveau while timerActive: end = pygame.time.get_ticks() timerActive = False duree = int((end - start)/1000) label = myfont.render("Nombre de Morts : " + str(morts), 1, (255,0,0)) screen.blit(label, (700/2-label.get_rect().width/2, 90)) label = myfont.render("Temps : " + str(duree) + " secondes", 1, (255,0,0)) screen.blit(label, (700/2-label.get_rect().width/2, 130)) screen.blit(tryAgainBannerTexture, ((700/2-170, 484))) Button(3, 200, 500, 300, 50) Button(2, 200, 600, 300, 50) # -- METTRE A JOUR LA FENETRE -- pygame.display.flip() # ---- LIMITER A 60 IMAGES PAR SECONDE ---- clock.tick(60) # -------- FAIRE BOUGER LE JOUEUR -------- def MovePlayer(rot, tempX, tempY, move, moveDir): # ------ § Variables § ------ global x, y global prevRotation global playerTexture playerTexture = pygame.transform.rotate(playerTexture, rot-prevRotation) prevRotation = rot if (0 <= x+tempX < mapSize and 0 <= y+tempY < mapSize): if(Map[x+tempX][y+tempY] != 1): return(move + moveDir) else: return(move) else: return(move) # -------- EDITEUR DE CARTE -------- def LevelEditor(): pygame.display.set_caption("The Maze | Level Editor") # ------ § Variables § ------ global x, y global startPos global imageSize # Importer des images ImportTextures(50) # Uniformiser les Pieges for i in range (mapSize): for j in range (mapSize): if (Map[i][j] >= 10 and Map[i][j] < 50): Map[i][j] = 5 elif (Map[i][j] >= 50 and Map[i][j] < 90): Map[i][j] = 6 isRunning = True actionExectued = True # ------ BOUCLE PRINCIPAL ------ while isRunning: # ---- BOUCLE D'EVENEMENT ---- for event in pygame.event.get(): # Coordonee du click mousePosition = pygame.mouse.get_pos() pressed = pygame.mouse.get_pressed() mpx, mpy = int(mousePosition[0]/50), int(mousePosition[1]/50) if (event.type == pygame.QUIT): isRunning = False if (event.type == pygame.KEYDOWN): if (event.key == pygame.K_UP): y -= 1 actionExectued = True if (event.key == pygame.K_DOWN): y += 1 actionExectued = True if (event.key == pygame.K_RIGHT): x += 1 actionExectued = True if (event.key == pygame.K_LEFT): x -= 1 actionExectued = True if (event.key == pygame.K_s): SaveWorld() if (event.key == pygame.K_l): LoadWorld() actionExecuted = True if (event.key == pygame.K_n): BlankWorld() actionExecuted = True if (event.key == pygame.K_m): ShowMap() ImportTextures(50) if (event.key == pygame.K_p): PlayGame() ImportTextures(50) # Uniformiser les Pieges for i in range (mapSize): for j in range (mapSize): if (Map[i][j] >= 10 and Map[i][j] < 50): Map[i][j] = 5 elif (Map[i][j] >= 50 and Map[i][j] < 90): Map[i][j] = 6 actionExecuted = True if (event.key == pygame.K_g): if(startPos != (0, 0)): Map[startPos[0]][startPos[1]] = 0 Map[x-7+mpx][y-7+mpy] = 3 startPos = (x-7+mpx, y-7+mpy) if (event.key == pygame.K_h): Map[x-7+mpx][y-7+mpy] = 4 if (event.type == pygame.MOUSEBUTTONUP): if(0 <= x-7+mpx < mapSize and 0 <= y-7+mpy < mapSize): if(event.button == 1): if(Map[x-7+mpx][y-7+mpy] == 1): Map[x-7+mpx][y-7+mpy] = 0 else: Map[x-7+mpx][y-7+mpy] = 1 if(event.button == 3): if(Map[x-7+mpx][y-7+mpy] == 5): Map[x-7+mpx][y-7+mpy] = 6 elif(Map[x-7+mpx][y-7+mpy] == 6): Map[x-7+mpx][y-7+mpy] = 0 else: Map[x-7+mpx][y-7+mpy] = 5 actionExecuted = True # ---- LOGIQUE DU JEU ---- # Si une action a ete executer if (actionExectued == True): # -- EFFACER L'ECRAN -- # Ne pas mettre de commande pour dessiner au dessus! screen.fill(BLACK) DrawScreen(imageSize, 7, 7) # -- METTRE A JOUR LA FENETRE -- pygame.display.flip() actionExecuted = False # ---- LIMITER A 60 IMAGES PAR SECONDE ---- clock.tick(60) def ShowMap(): pygame.display.set_caption("The Maze | Map") # ------ § Variables § ------ global x, y global imageSize x = mapSize//2 y = mapSize//2 # Importer des images ImportTextures(700//mapSize) isShowingMap = True # ------ BOUCLE PRINCIPAL ------ while isShowingMap: # ---- BOUCLE D'EVENEMENT ---- for event in pygame.event.get(): if (event.type == pygame.QUIT): isShowingMap = False if (event.type == pygame.KEYDOWN): if (event.key == pygame.K_m): isShowingMap = False # ---- LOGIQUE DU JEU ---- # -- EFFACER L'ECRAN -- # Ne pas mettre de commande pour dessiner au dessus! screen.fill(BLACK) DrawScreen(imageSize, mapSize//2, mapSize//2) # -- METTRE A JOUR LA FENETRE -- pygame.display.flip() # ---- LIMITER A 60 IMAGES PAR SECONDE ---- clock.tick(60) # -------- DESSINER LE TERRAIN -------- def DrawScreen(imgS, tempM, tempP): # ------ § Variables § ------ k = 0 l = 0 for i in range (y-tempM, y+tempP): for j in range (x-tempM, x+tempP): if (0 <= i < mapSize and 0 <= j < mapSize): texture = finTextures[0] #GROUND if(Map[j][i] == 1): texture = finTextures[1] #WALL elif(Map[j][i] == 3): texture = finTextures[3] #START elif(Map[j][i] == 4): texture = finTextures[4] #GOAL elif(Map[j][i] == 5): texture = finTextures[5] #TRAP elif(Map[j][i] == 6): texture = finTextures[6] #DECOR # TRAPS elif(Map[j][i] == 10): texture = trapTextures[0] elif(Map[j][i] == 11): texture = trapTextures[1] elif(Map[j][i] == 12): texture = trapTextures[2] #DECORS elif(Map[j][i] == 50): texture = decorTextures[0] elif(Map[j][i] == 51): texture = decorTextures[1] elif(Map[j][i] == 52): texture = decorTextures[2] else: texture = finTextures[2] #WASTELAND screen.blit(texture, (l*imgS[0], k*imgS[1])) l += 1 l = 0 k += 1 # -------- SAUVEGARDE DE LA CARTE -------- def SaveWorld(): print("SAVE START") try: file_path = filedialog.asksaveasfilename(defaultextension=".maze", filetypes=(("Text Files", "*.maze"),("All Files", "*.*"))) levelText = open(file_path, "w+") #Write and Overwrite for i in range (mapSize): for j in range (mapSize): levelText.write(str(Map[i][j])) levelText.write("\n") levelText.close() print("(Y) SAVE COMPLETE", end="\n\n") except Exception as e: print("(N)SAVE FAILURE:\n -->", e, end="\n\n") pass # -------- CHARGEMENT DE LA CARTE -------- def LoadWorld(): # ------ § Variables § ------ global startPos print("LOAD START") try: file_path = filedialog.askopenfilename(defaultextension=".maze", filetypes=(("Text Files", "*.maze"),("All Files", "*.*"))) levelText = open(file_path, "r") #Read Only for i in range(mapSize): read = levelText.read(mapSize) for j in range(mapSize): Map[i][j] = int(read[j]) if(int(read[j]) == 3): startPos = (i, j) levelText.read(1) print("(Y) LOAD COMPLETE", end="\n\n") except Exception as e: print("(N) LOAD FAILURE:\n -->", e, end="\n\n") # -------- CHARGEMENT D'UN LEVEL -------- def LoadLevel(level): # ------ § Variables § ------ global startPos print("LEVEL LOAD START") try: file_path = level levelText = open(file_path, "r") #Read Only for i in range(mapSize): read = levelText.read(mapSize) for j in range(mapSize): Map[i][j] = int(read[j]) if(int(read[j]) == 3): startPos = (i, j) levelText.read(1) print("(Y) LOAD COMPLETE", end="\n\n") except Exception as e: print("(N) LOAD FAILURE:\n -->", e, end="\n\n") MainMenu() pygame.quit()