def makeCreditText(self): self.texts = [ ((self.font.render("Glitch_Heaven, a game by:", False, (255, 255, 255))).convert_alpha(), (50, 100)), (makeGlitched("Penaz", self.font), (50, 120)), ((self.font.render("Thanks to:", False, (255, 255, 255))).convert_alpha(), (50, 150)), (makeGlitched("Dexter561, ScansPlays and AstralGemini", self.font), (50, 170)), ((self.font.render("--- Special Thanks ---", False, (255, 255, 255))).convert_alpha(), (50, 220)), ( (self.font.render("[Many names to be put here in the future]", False, (255, 255, 255))).convert_alpha(), (50, 240), ), ]
def makeSDMenu(self): if self.config["Unlockables"]["CFMode"]: self.sdimg = self.font.render("Start 'Critical Failure' Mode", False, (255, 255, 255)).convert_alpha() self.sdselimg = makeGlitched("Start 'Critical Failure' Mode", self.font) self.sd = menuitem(self.sdimg, self.sdselimg, (50, 420), lambda: self.editDesc( "Escape before the time runs out." ), lambda: CFMenu( self.screen, self.keys, self.config, self.sounds, self.modifiers, self.mainLogger).mainLoop(), self.config, self.sounds) self.activeItems.append(self.sd) else: self.sdimg = self.font.render("(File Corrupted)", False, (100, 100, 100)).convert_alpha() self.sd = menuitem(self.sdimg, self.sdimg, (50, 420), lambda: self.editDesc(None), lambda: None, self.config, self.sounds) self.items.append(self.sd)
def makeModifierMenuItem(self): if self.config["Unlockables"]["modifiers"]: self.chimg = self.font.render("Modifiers Menu", False, (255, 255, 255)).convert_alpha() self.chselimg = makeGlitched("Modifiers Menu", self.font) self.cb = menuitem(self.chimg, self.chselimg, (50, 480), lambda: self.editDesc( "Access the mods menu"), lambda: modMenu(self.screen, self.keys, self.config, self.sounds, self.modifiers, self.mainLogger ).mainLoop(), self.config, self.sounds) self.activeItems.append(self.cb) else: self.chimg = self.font.render("(File Corrupted)", False, (100, 100, 100)).convert_alpha() self.cb = menuitem(self.chimg, self.chimg, (50, 480), lambda: self.editDesc(None), lambda: None, self.config, self.sounds) self.items.append(self.cb)
def makeLoadItem(self): self.load = self.font.render("Open", False, (255, 255, 255)).convert_alpha() self.loadsel = makeGlitched("Open", self.font) self.loadgame = menuItem.menuitem(self.load, self.loadsel, (250, 560), lambda: self.editDesc( "Open This map"), lambda: self.openMap( self.dirlist[self.id][:-4]), self.config, self.sounds) self.activeItems.append(self.loadgame) self.items.append(self.loadgame)
def makeLoadItem(self): self.load = self.font.render("Load", False, (255, 255, 255)).convert_alpha() self.loadsel = makeGlitched("Load", self.font) self.loadgame = menuItem.menuitem(self.load, self.loadsel, (250, 560), lambda: self.editDesc( "Load the selected campaign"), lambda: self.loadGame( self.dirlist[self.id] ), self.config, self.sounds) self.activeItems.append(self.loadgame) self.items.append(self.loadgame)
def makeLoadItem(self): self.load = self.font.render("Open", False, (255, 255, 255)).convert_alpha() self.loadsel = makeGlitched("Open", self.font) self.loadgame = menuItem.menuitem(self.load, self.loadsel, (250, 560), lambda: self.editDesc( "Explore this directory"), lambda: loadSingleFileMenu( self.screen, self.keys, self.config, self.sounds, self.modifiers, self.mainLogger, self.dirlist[self.id] ).mainLoop(), self.config, self.sounds) self.activeItems.append(self.loadgame) self.items.append(self.loadgame)
def KeySelect(self, font, key, config, keys): selecting = True self.mod_logger.debug("Entering the keychange \ event loop , Key is %s" % key) while selecting: for event in pygame.event.get(): if event.type == pygame.KEYDOWN: self.unselectedimg = font.render( (str(pygame.key.name(event.key))).upper(), False, (255, 255, 255)).convert_alpha() self.selectedimg = makeGlitched( (str(pygame.key.name(event.key))).upper(), font) self.image = self.selectedimg config["Controls"][str(key)] = event.key with open("config.json", "w") as conf: conf.write(json.dumps(config, indent=4)) keys[key] = event.key selecting = False self.mod_logger.debug("Key Changed to %s" % pygame.key.name(event.key))
def editDesc(self, string): self.desc = makeGlitched(string, self.font)
def __init__(self, screen, keys, config, sounds, log): self.logSectionName = "mainMenu" super().__init__(screen, keys, config, sounds, log) self.dbtxt = makeGlitched( "Debug Mode Active, Keydebug Active: {0}".format( config["Debug"]["keydebug"]), self.font)
def __init__(self, text, location, onhover, function, config, sounds, log, font): self.unselimg = font.render(text, False, self.white).convert_alpha() self.selimg = makeGlitched(text, font) super().__init__(self.unselimg, self.selimg, location, onhover, function, config, sounds, log)
def main(self, screen, keys, mode, cmp, config, sounds, modifiers, log): """ Main Game method Keyword Arguments: - Screen: The surface to draw the game to. - keys: The control keys to use. - Mode: Identifies the mode of the game (newgame, load, singlemap, criticalfailure, cfsingle) - cmp: campaign file - config: Game configuration instance - sounds: Sounds dictionary instance - modifiers: Modifiers Dictionary instance - log: The main logger, inherited by the bootstrapper """ self.showMessage = False self.messageTime = _defaultMessageTime_ self.messageSurf = None self.SaveFile = None self.showCollision = False self.activeHelpList = [] self.gameStatus = { "campaignFile": None, "campaignName": None, "mode": mode, "cftime": None, "time": 0., "deathCounter": 0, "modifiers": modifiers, "currentLevel": None } self.oldComponentPaths = { "background": None, "middle_back1": None, "middle_back2": None } self.componentPaths = { "background": None, "middle_back1": None, "middle_back2": None } self.components = { "background": None, "middle_back1": None, "middle_back2": None } self.oldoverpath = None self.mainLogger = log self.mod_logger = log.getChild("game") self.mod_logger.info("Entering main game") self.running = True self.showFPS = False self.titletxt = None self.gravity = 1 self.sounds = sounds self.screensize = screen.get_size() self.gsize = (screen.get_width(), screen.get_height() - 24) self.gameviewport = pygame.surface.Surface(self.gsize) self.clock = pygame.time.Clock() self.titleholder = pygame.image.load(pjoin( "resources", "UI", "TitleHolder.png")) self.font = pygame.font.Font(pjoin( "resources", "fonts", "TranscendsGames.otf"), 20) self.loadWriting = self.font.render("Loading...", False, (255, 255, 255)) self.title, self.titleposition, self.player = 3 * [None] self.screen = screen self.keys = keys self.config = config self.helptxts = pygame.sprite.Group() self.plats = tmx.SpriteLayer() self.GlitchTriggers = tmx.SpriteLayer() self.mod_logger.debug("Current Active Modifiers: {0}".format( modifiers)) # Preloading graphics area # v-------------------------------------------------------------------v self.preloaded_sprites = { "platforms": pygame.image.load(pathjoin("resources", "tiles", "Plats.png") ).convert_alpha(), "glitches": pathjoin("resources", "sprites", "MobileObstacle.png"), "collectibleitem": pathjoin("resources", "sprites", "GlitchTrigger.png" ), "static": pygame.image.load(pathjoin("resources", "backgrounds", "screengarble.png") ).convert_alpha() } # ^-------------------------------------------------------------------^ # Defines if a level should be loaded or a # new campaign should be started. # It also defines the modes # v--------------------------------------------------------------v if self.gameStatus["mode"] == "load": self.mod_logger.debug("Using Load mode") try: self.loadGame(cmp) self.LoadLevel(self.gameStatus["currentLevel"], self.gameStatus["campaignName"], self.gameStatus["mode"], self.screen) except FileNotFoundError: self.mod_logger.info("No file provided, loading cancelled") self.running = False elif self.gameStatus["mode"] == "newgame": self.mod_logger.debug("Using New Game mode") self.gameStatus["campaignFile"] = cmp self.gameStatus["campaignName"] = splitext(basename(cmp))[0] self.loadCampaign(self.gameStatus["campaignFile"], self.gameStatus["mode"]) self.LoadLevel(self.gameStatus["currentLevel"], self.gameStatus["campaignName"], self.gameStatus["mode"], self.screen) elif self.gameStatus["mode"] in ["criticalfailure", "cfsingle"]: self.mod_logger.debug("Using New Game mode - \ Critical Failure Modifier") self.gameStatus["cftime"] = 0 self.gameStatus["campaignFile"] = cmp self.gameStatus["campaignName"] = splitext(basename(cmp))[0] self.loadCampaign(self.gameStatus["campaignFile"], self.gameStatus["mode"]) self.redsurf = pygame.surface.Surface(self.gsize, pygame.SRCALPHA) linesize = 3 bot = self.redsurf.get_rect().bottom self.redsurf.fill((255, 0, 0, 50)) self.redsurf.fill((255, 255, 255, 255), pygame.rect.Rect(0, bot - linesize, self.gsize[0], linesize)) self.redsurfrect = self.redsurf.get_rect() self.LoadLevel(self.gameStatus["currentLevel"], self.gameStatus["campaignName"], self.gameStatus["mode"], self.screen) elif self.gameStatus["mode"] == "singlemap": self.RealLoadLevel(cmp, "singlemap", self.screen) # ^--------------------------------------------------------------^ self.fps = 60 self.garble = False self.garbletimer = _garbletimer_ self.deadbodies = pygame.sprite.Group() pygame.display.set_caption("Glitch_Heaven - Pre-Pre-Alpha Version") if self.running: self.loadLevelPart2(self.keys, sounds) self.mod_logger.debug("Glitches Loaded: {0}".format(self.glitches)) """Game Loop""" while self.running: dt = min(self.clock.tick(self.fps)/1000., 0.05) # For Critical Failure mode # v-------------------------------------------------------------------v if self.gameStatus["mode"] in ["criticalfailure", "cfsingle"]: self.gameStatus["time"] += dt self.redsurfrect.y = -self.gsize[1] + \ (self.gsize[1] * self.gameStatus["time"]) \ / self.gameStatus["cftime"] self.rcftime = self.gameStatus["cftime"] \ - self.gameStatus["time"] self.timer = makeGlitched("Time Before Failure: {0}".format( str(timedelta(seconds=self.rcftime))), self.font) if self.redsurfrect.y > 0: pygame.mouse.set_visible(True) # Make the cursor visible self.running = False # ^-------------------------------------------------------------------^ # For Chaos Mode # v-------------------------------------------------------------------v if self.gameStatus["modifiers"]["chaos"]: self.chaosParameters["timer"] -= dt if self.chaosParameters["timer"] <= 0.: self.toggleGlitch(choice( self.chaosParameters["glitches"]), True) self.newChaosTime() # ^-------------------------------------------------------------------^ for event in pygame.event.get(): if event.type == pygame.QUIT: self.mod_logger.info("QUIT signal received, quitting") pygame.quit() quit() # Debug Area - Glitch Toggles # v----------------------------------------------------------v mods = pygame.key.get_mods() # if config.getboolean("Debug", "debugmode") and\ if config["Debug"]["debugmode"] and\ mods & pygame.KMOD_LSHIFT and\ mods & pygame.KMOD_LCTRL and\ mods & pygame.KMOD_LALT: if event.type == pygame.KEYDOWN: if event.key in _debugkeys_: self.toggleGlitch(_debugkeys_[event.key], True) if event.key == pygame.K_RETURN: self.garble = True if event.key == pygame.K_BACKSPACE and\ self.gameStatus["mode"] not in ["singlemap"]: self.mod_logger.debug("Debug key used, " + "Loading next level") level = self.forceNextLevel() self.LoadLevel(level, self.gameStatus["campaignName"], self.gameStatus["mode"], self.screen) if level: self.loadLevelPart2(self.keys, sounds) if event.key == pygame.K_KP_DIVIDE: self.mod_logger.info( "Toggled Collision Rectangle View") self.showCollision = not self.showCollision if event.key == pygame.K_KP_MULTIPLY: self.showFPS = not self.showFPS if event.key == pygame.K_c: self.mod_logger.info("Forced Checkpoint Save") self.player.lastcheckpoint = ( self.player.rect.x, self.player.rect.y) # Temporary toggles for pause menu and saveGame # v----------------------------------------------------------v elif event.type == pygame.KEYDOWN and\ event.key == keys["escape"]: pauseMenu(screen, keys, self, self.config, sounds, self.mainLogger).mainLoop() elif event.type == pygame.KEYDOWN and\ event.key == self.keys["restart"]: self.sprites.remove(*self.deadbodies) self.deadbodies.empty() self.player.respawn(self) # if config.getboolean("Debug", "keydebug") and\ if config["Debug"]["keydebug"] and\ event.type == pygame.KEYDOWN: self.mod_logger.debug("A key was pressed: {0}" .format(pygame.key.name(event.key))) # ^----------------------------------------------------------^ self.backpos = self.givePosition(__floordiv__, 6) self.middlebackpos = self.givePosition(__floordiv__, 4) self.middlepos = self.givePosition(__floordiv__, 2) self.gameviewport.blit(self.components["background"], self.backpos) self.gameviewport.blit(self.components["middle_back1"], self.middlebackpos) self.tilemap.update(dt, self) self.gameviewport.blit(self.components["middle_back2"], self.middlepos) self.tilemap.draw(self.gameviewport) self.helptxts.update(dt, self) if not self.glitches["timeLapse"] or self.player.x_speed != 0: self.particlesurf.fill((0, 0, 0, 0)) self.player.particles.update() self.player.particles.draw(self.particlesurf) self.gameviewport.blit(self.particlesurf, (-self.tilemap.viewport.x, -self.tilemap.viewport.y)) if self.hasOverlay: self.gameviewport.blit(self.overlay, self.givePosition(__mul__, 1.5)) if self.gameStatus["mode"] in ["criticalfailure", "cfsingle"]: self.gameviewport.blit(self.redsurf, (0, self.redsurfrect.y)) if self.gameStatus["modifiers"]["vflip"] or\ self.gameStatus["modifiers"]["hflip"]: self.gameviewport = pygame.transform.flip( self.gameviewport, self.gameStatus["modifiers"]["hflip"], self.gameStatus["modifiers"]["vflip"]) screen.blit(self.gameviewport, (0, 0)) if self.gameStatus["mode"] in ["criticalfailure", "cfsingle"]: screen.blit(self.timer, (50, 70)) screen.blit(self.titleholder, (0, self.gsize[1])) screen.blit(self.title, self.titleposition) # if config.getboolean("Video", "deathcounter"): if config["Video"]["deathcounter"]: self.dcounttxt = makeGlitched( "Deaths: %d" % self.gameStatus["deathCounter"], self.font) screen.blit(self.dcounttxt, (50, 50)) if self.garble: screen.blit(self.preloaded_sprites["static"], (0, 0)) self.garbletimer -= dt if self.garbletimer <= 0: self.garble = False self.garbletimer = _garbletimer_ if self.showCollision: rec = self.player.collisionrect.copy() rec.x, rec.y = self.tilemap.pixel_to_screen( self.player.collisionrect.x, self.player.collisionrect.y) pygame.draw.rect(screen, (255, 0, 0), rec, 1) if self.showFPS: fps = self.font.render(str(1/dt), False, (255, 0, 0)) screen.blit(fps, (screen.get_width() - 50, screen.get_height() - 50)) if self.showMessage: self.messageSurf.update(dt) self.messageTime -= dt rect = self.messageSurf.surface.get_rect() screen.blit(self.messageSurf.surface, self.tilemap.pixel_to_screen(self.player.rect.x - rect.width/2 + 16, self.player.rect.y - rect.height)) if self.messageTime <= 0: self.showMessage = False self.messageTime = _defaultMessageTime_ pygame.display.update()
def RealLoadLevel(self, path, mode, screen): """ Loads a level structure, given path, mode and screen Keyword Arguments: - path: Full path to the level - mode: Mode to open the level in - screen: The screen instance """ self.mod_logger.info("LoadLevel Routine is loading %(path)s" % locals()) # Erases level and if we're doing a campaign, checks for intermissions # v--------------------------------------------------v self.eraseCurrentLevel() self.showLoadingScreen() if mode not in ["singlemap"]: self.checkIntermission() # ^--------------------------------------------------^ self.showLoadingScreen() # Loads the level configuration and its chaos parameters # v--------------------------------------------------v with open(path+".json") as f: levelconfig = json.loads(f.read()) self.mod_logger.debug("Level configuration loaded") self.loadChaosParameters(levelconfig) # ^--------------------------------------------------^ # If we're in the single timer Critical Failure, load the level time # And reset the time to 0. # v--------------------------------------------------v if mode == "cfsingle": self.gameStatus["cftime"] = levelconfig["Level Info"]["CFTime"] self.gameStatus["time"] = 0. # ^--------------------------------------------------^ # Loads the level glitches # v--------------------------------------------------v self.glitches = levelconfig["Glitches"]["Standard"] self.mod_logger.debug("Glitches Active: {0}".format(self.glitches)) # ^--------------------------------------------------------------^ # Loads the level map # v--------------------------------------------------------------v self.mod_logger.debug("Loading Tilemap") self.tilemap = tmx.load(path+".tmx", self.screensize) self.mod_logger.debug("Tilemap Loaded, building map") # ^--------------------------------------------------------------^ # Loads backgrounds and overlays, optimised in case # the same ones are used # v--------------------------------------------------------------v self.mod_logger.debug("Loading Backgrounds") self.oldComponentPaths = self.componentPaths.copy() for key in self.componentPaths.keys(): self.componentPaths[key] = pjoin("resources", "backgrounds", levelconfig["Level Components"] [key]) if self.componentPaths[key] != self.oldComponentPaths[key]: self.components[key] = pygame.image.load( self.componentPaths[key]).convert_alpha() self.hasOverlay = levelconfig["Level Components"]["overlay"]\ is not None if self.hasOverlay: self.overpath = pjoin("resources", "overlays", levelconfig["Level Components"] ["overlay"]) if self.overpath != self.oldoverpath: self.overlay = pygame.image.load(self.overpath).convert_alpha() # ^--------------------------------------------------------------^ # Creates all the mobile obstacles # v--------------------------------------------------------------v self.obstacles = tmx.SpriteLayer() for obstacle in self.tilemap.layers['Triggers'].find('Obstacle'): Obstacle((obstacle.px, obstacle.py), ("v" in obstacle['Obstacle']), obstacle['ObsSpeed'], None, self.obstacles, preloaded_ani=self.preloaded_sprites["glitches"]) self.tilemap.layers.append(self.obstacles) # ^--------------------------------------------------------------^ # Creates all the triggerable platforms # v--------------------------------------------------------------v for platform in self.tilemap.layers['Triggers'].find('Platform'): bouncy = "bouncyplat" in platform bouncepwr = int(platform['bouncyplat']) if bouncy else 0 TriggerablePlatform( platform.px, platform.py, ("v" in platform['Platform']), bouncepwr, int(platform['PlatSpeed']), int(platform['PlatSize']), False, platform['id'], self.plats, game=self, bouncy=bouncy, image=self.preloaded_sprites["platforms"]) self.tilemap.layers.append(self.plats) # Creates all the lasers # v--------------------------------------------------------------v self.lasers = tmx.SpriteLayer() for laser in self.tilemap.layers['Triggers'].find('Laser'): time = laser['Laser'] number = 0 if 'id' in laser: number = laser['id'] size = (laser.width, laser.height) vertical = size[1] > size[0] definingsize = size[1] if vertical else size[0] Laser(definingsize, vertical, time, number, (laser.px, laser.py), self.lasers) self.tilemap.layers.append(self.lasers) # ^--------------------------------------------------------------^ # Creates all the buttons # v--------------------------------------------------------------v self.btns = tmx.SpriteLayer() for btn in self.tilemap.layers['Triggers'].find('button'): ident = btn['button'] password = None msg="" if "password" in btn: password = btn["password"] if "message" in btn: msg = btn["message"] button((btn.px, btn.py), ident, password, self.btns, message=msg) self.tilemap.layers.append(self.btns) # ^--------------------------------------------------------------^ # Creates all the checkpoints # v--------------------------------------------------------------v self.checkpoints = tmx.SpriteLayer() for chk in self.tilemap.layers["Triggers"].find('CheckPoint'): checkPoint((chk.px, chk.py), self.checkpoints) self.tilemap.layers.append(self.checkpoints) # ^--------------------------------------------------------------^ # Creates all the glitch toggles # v--------------------------------------------------------------v for trig in self.tilemap.layers['Triggers'].find('ToggleGlitch'): if "message" in trig: msg = trig["message"] else: msg = "" self.GlitchTriggers.add(CollectibleTrigger( trig.px, trig.py, self, trig['ToggleGlitch'], preloaded_animation=self.preloaded_sprites[ "collectibleitem" ], message=msg)) self.tilemap.layers.append(self.GlitchTriggers) # ^--------------------------------------------------------------^ # In case of critical failure modes, further garbles # level title texts, then renders the title # v--------------------------------------------------------------v if self.gameStatus["mode"] in ["criticalfailure", "cfsingle"]: self.titletxt = makeMoreGlitched( str(levelconfig['Level Info']['Name']), 50) else: self.titletxt = str(levelconfig['Level Info']['Name']) self.title = makeGlitched(self.titletxt, self.font) # ^--------------------------------------------------------------^ # Finds the center position of the title # v--------------------------------------------------------------v center = (self.screensize[0] - int(self.title.get_rect().width))/2 self.titleposition = (center, self.gsize[1] + 2) # ^--------------------------------------------------------------^ self.mod_logger.info("Map Loaded and built Successfully") # ^--------------------------------------------------------------^ if self.config["General"]["autosaving"] and self.SaveFile: self.mod_logger.debug("Saved with data: {0}" % self.gameStatus) with open(self.SaveFile, "w") as savefile: savefile.write(json.dumps(self.gameStatus)) """self.mod_logger.info("Game autosaved on the file: {0}" % (self.SaveFile))""" message = levelconfig["Message"] if message != "": self.showMessage = True self.messageSurf = animatedText(message)