My entry for the VimJam2
https://justayte.itch.io/pinmik-panik
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
9.5 KiB
232 lines
9.5 KiB
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.Surface((self.DISPLAY_WIDTH,self.DISPLAY_HEIGHT)) |
|
self.screen = pygame.display.set_mode((self.DISPLAY_WIDTH,self.DISPLAY_HEIGHT),pygame.RESIZABLE) |
|
self.screenw,self.screenh = self.DISPLAY_WIDTH,self.DISPLAY_HEIGHT |
|
self.screenoffx,self.screenoffy = 0,0 |
|
self.resizescreenw,self.resizescreenh = 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.globals["pause"] = False |
|
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) |
|
self.sound_lib["bgm/menu.ogg"].play(-1) |
|
|
|
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.VIDEORESIZE: |
|
self.screenw,self.screenh = int(event.w),int(event.h) |
|
self.screen = pygame.display.set_mode((self.screenw,self.screenh),pygame.RESIZABLE) |
|
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 |
|
|
|
x,y = pygame.mouse.get_pos() |
|
x-=self.screenoffx |
|
y-=self.screenoffy |
|
x/=self.resizescreenw/self.DISPLAY_WIDTH |
|
y/=self.resizescreenh/self.DISPLAY_HEIGHT |
|
self.inputs["mouse"]["pos"] = x,y |
|
|
|
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))
|
|
|