import pygame, os, math, time import gamedata.definitions as lib import gamedata.scenes as scenes import gamedata.objects.gameloop as gameloop from gamedata.objects.particles import Particle class Game(): def __init__(self): self.DISPLAY_WIDTH, self.DISPLAY_HEIGHT = 1280, 720 self.window = pygame.Surface((self.DISPLAY_WIDTH,self.DISPLAY_HEIGHT)) self.realwindow = pygame.display.set_mode((self.DISPLAY_WIDTH,self.DISPLAY_HEIGHT)) pygame.display.set_caption("Pinmik Panik !") pygame.init() pygame.mixer.init() font = "gamedata/font.ttf" self.fontfile = pygame.font.Font(font,32) self.fontfilesmall = pygame.font.Font(font,16) self.fontfilebig = pygame.font.Font(font,64) self.logs = [] self.running = True self.init_inputs() self.gameloop = gameloop.GameLoop() # Je crée une boucle de jeu def load_image(filename): return pygame.image.load(filename).convert_alpha() self.sprite_lib = self.init_assets("gamedata/assets/",load_image) # Dico qui contient chaques images du dossier assets pygame.display.set_icon(self.sprite_lib["icon.png"]) self.sound_lib = self.init_assets("gamedata/sounds/",pygame.mixer.Sound) # Pareil, mais pour les musiques / sons self.sound_volumes = {} for i in self.sound_lib.keys(): self.sound_volumes[i] = 1 self.spriteLists = {} # Tiendra des listes préarrangées self.scenes = scenes # Je stoque mes modules à l'intérieur de ma classe pour y avoir accès partout self.scene = None self.lib = lib self.pygame = pygame self.math = math self.elapsedtime = 0 self.datadir = lib.get_save_dir("pinmikpanik") self.dataname = "highscore.ini" self.settingsname = "settings.ini" highscore = lib.loadscore(self.datadir,self.dataname) bgm,sfx = lib.loadsettings(self.datadir,self.settingsname) bgm,sfx = bgm/100,sfx/100 self.globals = {} # Un dico pour ranger toute les valeurs globales, pour communiquer entre objets par exemples self.globals["camerax"] = 0 self.globals["cameray"] = 0 self.globals["scamerax"] = 3 self.globals["scameray"] = 0 self.globals["debug"] = False self.globals["highscore"] = highscore self.scaleCamera() self.globals["bgmvolume"] = bgm self.globals["sfxvolume"] = sfx self.reinit_volumes() self.pasttime = time.time() # Je charge la scene de base scenes.main(self) def set_camera(self,posx,posy): self.globals["camerax"], self.globals["cameray"] = posx,posy def log(*args): args[0].logs.append(" ".join(args[1:])) print(" ".join(args[1:])) def reinit_volumes(self): for i in self.sound_lib.keys(): # J'applique de base les volumes if i.startswith("sfx/"): self.sound_lib[i].set_volume(self.globals["sfxvolume"]*self.sound_volumes[i]) if i.startswith("bgm/"): self.sound_lib[i].set_volume(self.globals["bgmvolume"]*self.sound_volumes[i]) def set_volume(self,sound,newvolume): self.sound_volumes[sound] = newvolume self.reinit_volumes() def game_loop(self): self.dt = time.time()-self.pasttime self.elapsedtime += self.dt self.pasttime = time.time() self.check_events() # Détecte les entrées clavier self.window.fill((0)*3) # Remplis l'écran de noir if self.gameloop: # Si j'ai une boucle de jeu, la lancer self.gameloop.step(self) # La logique de la boucle self.gameloop.draw(self) # L'affichage de la boucle if self.scene : self.scene(self) self.scene = False pygame.display.update() # Mettre à jour l'affichage def init_inputs(self): self.inputs = {} self.inputs["unicode"] = "" self.inputs["mouse"] = { "pos" : [0,0], # Position "rel" : [0,0], # Mouvement relatif "click" : 0 # Timer du click } self.inputs["keys"] = { "escape":{ "timer" : 0, # Timer de la touche "realtime" : 0, # Temps réel préssé "pressed" : False, "keycode" : pygame.K_ESCAPE # Code pygame de la touche en question } } self.no_unicode = [pygame.K_ESCAPE,pygame.K_BACKSPACE,pygame.K_RETURN] def check_events(self): self.inputs["unicode"] = "" for event in pygame.event.get(): if event.type == pygame.QUIT: self.running = False if event.type == pygame.KEYDOWN: for i in self.inputs["keys"].keys(): if event.key == self.inputs["keys"][i]["keycode"]: # Vérifie si une des touches du dico est préssée self.inputs["keys"][i]["pressed"] = True else: if event.key not in self.no_unicode: self.inputs["unicode"] = event.unicode # Je récupère la "lettre" de la touche préssée if event.type == pygame.KEYUP: for i in self.inputs["keys"].keys(): if event.key == self.inputs["keys"][i]["keycode"]: # Vérifie si une des touches du dico est préssée self.inputs["keys"][i]["pressed"] = False self.inputs["mouse"]["pos"] = pygame.mouse.get_pos() # Position self.inputs["mouse"]["rel"] = pygame.mouse.get_rel() # Déplacement par rapport à la frame précédente # Getting mouse position on camera mx = self.inputs["mouse"]["pos"][0]*self.globals["cameraw"]/self.DISPLAY_WIDTH+self.globals["camerax"] my = self.inputs["mouse"]["pos"][1]*self.globals["camerah"]/self.DISPLAY_HEIGHT+self.globals["cameray"] self.inputs["mouse"]["campos"] = [mx,my] # Augmente le timer si la touche est préssée, le reset sinon for i in self.inputs["keys"].keys(): if self.inputs["keys"][i]["pressed"]: self.inputs["keys"][i]["timer"]+=1 self.inputs["keys"][i]["realtime"]+=self.dt else: self.inputs["keys"][i]["timer"]=0 self.inputs["keys"][i]["realtime"]=0 # Timer du click boutons = pygame.mouse.get_pressed() if boutons[0]: # Si click gauche self.inputs["mouse"]["click"]+=1 else: self.inputs["mouse"]["click"] = 0 def init_assets(self,path,function,recursive=True): dico = {} self.scan_dir(path,path,dico,function,recursive) return dico def scan_dir(self,dirpath,origin,dico,function,recursive=True): scanner = os.scandir(path=dirpath) for i in scanner: # Je passe à travers toutes les données d'un dossier, fichiers et sous dossiers compris # i.path est le chemin du fichier, par exemple # Si c'est une image, je l'importe et l'ajoute à la librairie finalpath = i.path.replace("\\","/") if i.is_file() or not recursive: finalpath = finalpath.replace(origin,'') # J'enleve l'origine (dans ce cas 'assets/' car c'est redontant, tout les sprites sont dedans dico[finalpath] = function(i.path) # Si c'est un dossier, je répete l'opération mais à l'intérieur de celui ci if i.is_dir() and recursive: self.scan_dir(i.path,origin,dico,function,recursive) scanner.close() def getSpriteDir(self,directory,ext=".png",assetdir="sprite_lib"): keys = (directory,ext,assetdir) assetdir = getattr(self,assetdir) # Si je ne précise pas quel type de ressource, je cherche dans mes sprites if keys in self.spriteLists.keys(): return self.spriteLists[keys] else: # Organise les sprites sprite_list = [] index = 0 while directory+str(index)+ext in assetdir.keys(): sprite_list.append(assetdir[directory+str(index)+ext]) index+=1 # Le stoque pour éviter de les réorganiser à chaque fois self.spriteLists[keys] = sprite_list return sprite_list def addParticle(self,sprites,posx,posy,velx=0,vely=0,modvelx=0,modvely=0,flipx=False,flipy=False,fps=15): p = Particle(self,sprites,posx,posy,velx,vely,modvelx,modvely,flipx,flipy,fps) self.gameloop.summon(p) def scaleCamera(self,neww=None,newh=None): if not neww: neww=self.DISPLAY_WIDTH if not newh: newh=self.DISPLAY_HEIGHT self.globals["cameraw"] = neww self.globals["camerah"] = newh self.globals["tempsubsurface"] = pygame.Surface((neww,newh))