class Main(ShowBase, FSM): """Main function of the application initialise the engine (ShowBase)""" def __init__(self): """initialise the engine""" ShowBase.__init__(self) FSM.__init__(self, "FSM-Game") # # BASIC APPLICATION CONFIGURATIONS # # disable pandas default camera driver self.disableMouse() # set background color to black self.setBackgroundColor(0, 0, 0) # set antialias for the complete sceen to automatic self.render.setAntialias(AntialiasAttrib.MAuto) helper.hide_cursor() # # CONFIGURATION LOADING # # load given variables or set defaults # check if audio should be muted mute = ConfigVariableBool("audio-mute", False).getValue() if mute: self.disableAllAudio() else: self.enableAllAudio() def setFullscreen(): """Helper function to set the window fullscreen with width and height set to the screens size""" # get the displays width and height w = self.pipe.getDisplayWidth() h = self.pipe.getDisplayHeight() # set window properties # clear all properties not previously set base.win.clearRejectedProperties() # setup new window properties props = WindowProperties() # Fullscreen props.setFullscreen(True) # set the window size to the screen resolution props.setSize(w, h) # request the new properties base.win.requestProperties(props) # check if the config file hasn't been created if not os.path.exists(prcFile): setFullscreen() elif base.appRunner: # When the application is started as appRunner instance, it # doesn't respect our loadPrcFiles configurations specific # to the window as the window is already created, hence we # need to manually set them here. for dec in range(mainConfig.getNumDeclarations()): # check if we have the fullscreen variable if mainConfig.getVariableName(dec) == "fullscreen": setFullscreen() # automatically safe configuration at application exit base.exitFunc = self.__writeConfig # due to the delayed window resizing and switch to fullscreen # we wait some time until everything is set so we can savely # proceed with other setups like the menus if base.appRunner: # this behaviour only happens if run from p3d files and # hence the appRunner is enabled taskMgr.doMethodLater(0.5, self.postInit, "post initialization", extraArgs=[]) else: self.postInit() def postInit(self): # # initialize game content # # Menus self.mainmenu = Mainmenu() self.optionsmenu = Optionsmenu() self.loadingscreen = LoadingScreen() self.music_menu = loader.loadMusic("music/menu.ogg") self.music_menu.setLoop(True) self.music_game = loader.loadMusic("music/game.ogg") self.music_game.setLoop(True) self.music_intro = loader.loadMusic("music/logos.ogg") # The games Intro def create16To9LogoCard(logoPath, tsName): cm = CardMaker("fade") scale = abs(base.a2dLeft) / 1.7776 cm.setFrame(-1, 1, -1 * scale, 1 * scale) logo = NodePath(cm.generate()) logo.setTransparency(TransparencyAttrib.MAlpha) logoTex = loader.loadTexture(logoPath) logoTs = TextureStage(tsName) logoTs.setMode(TextureStage.MReplace) logo.setTexture(logoTs, logoTex) logo.setBin("fixed", 5000) logo.reparentTo(render2d) logo.hide() return logo self.gfLogo = create16To9LogoCard("intro/GrimFangLogo.png", "gfLogoTS") self.pandaLogo = create16To9LogoCard("intro/Panda3DLogo.png", "pandaLogoTS") self.gameLogo = create16To9LogoCard("intro/GameLogo.png", "gameLogoTS") def createFadeIn(logo): return LerpColorScaleInterval(logo, 2, LVecBase4f(0.0, 0.0, 0.0, 1.0), LVecBase4f(0.0, 0.0, 0.0, 0.0)) def createFadeOut(logo): return LerpColorScaleInterval(logo, 2, LVecBase4f(0.0, 0.0, 0.0, 0.0), LVecBase4f(0.0, 0.0, 0.0, 1.0)) gfFadeInInterval = createFadeIn(self.gfLogo) gfFadeOutInterval = createFadeOut(self.gfLogo) p3dFadeInInterval = createFadeIn(self.pandaLogo) p3dFadeOutInterval = createFadeOut(self.pandaLogo) gameFadeInInterval = createFadeIn(self.gameLogo) gameFadeOutInterval = createFadeOut(self.gameLogo) self.introFadeInOutSequence = Sequence(Func(self.music_intro.play), Func(self.gfLogo.show), gfFadeInInterval, Wait(1.0), gfFadeOutInterval, Wait(0.5), Func(self.gfLogo.hide), Func(self.pandaLogo.show), p3dFadeInInterval, Wait(1.0), p3dFadeOutInterval, Wait(0.5), Func(self.pandaLogo.hide), Func(self.gameLogo.show), gameFadeInInterval, Wait(1.0), gameFadeOutInterval, Wait(0.5), Func(self.gameLogo.hide), Func(self.messenger.send, "intro_done"), Func(self.music_intro.stop), name="fadeInOut") # game intro end # collision setup base.cTrav = CollisionTraverser("base collision traverser") base.cTrav.setRespectPrevTransform(True) # setup default physics base.enableParticles() # # Event handling # self.accept("escape", self.__escape) # accept menu events self.accept("menu_start", self.request, ["Game"]) self.accept("menu_options", self.request, ["Options"]) self.accept("menu_quit", self.quit) self.accept("options_back", self.request, ["Menu"]) # game over self.accept("GameOver", self.demand, ["Menu"]) # # Start with the menu after the intro has been played # self.introFadeInOutSequence.start() self.accept("intro_done", self.request, ["Menu"]) # # FSM PART # def enterMenu(self): """Enter the main menu state""" helper.show_cursor() self.mainmenu.show() if self.music_menu.status() != AudioSound.PLAYING: self.music_menu.play() def exitMenu(self): """Leave the main menu state""" self.mainmenu.hide() def enterOptions(self): """Enter the options menu state""" self.optionsmenu.show() def exitOptions(self): """Leave the options menu state""" self.optionsmenu.hide() def enterGame(self): # main game code should be called here print _("Enter Game") self.loadingscreen.start() helper.hide_cursor() self.world = World() self.music_menu.stop() self.music_game.play() self.loadingscreen.stop() def exitGame(self): # cleanup for game code print _("Exit Game") helper.show_cursor() self.world.stop() del self.world # # FSM PART END # # # BASIC FUNCTIONS # def __escape(self): if self.state == "Off": self.introFadeInOutSequence.finish() elif self.state == "Menu": self.quit() elif self.state == "Game": if self.world.requestEscape(): self.request("Menu") else: self.request("Menu") def quit(self): """This function will stop the application""" self.userExit() def __writeConfig(self): """Save current config in the prc file or if no prc file exists create one. The prc file is set in the prcFile variable""" page = None volume = str(round(base.musicManager.getVolume(), 2)) mute = "#f" if base.AppHasAudioFocus else "#t" customConfigVariables = ["", "audio-mute", "audio-volume"] if os.path.exists(prcFile): # open the config file and change values according to current # application settings page = loadPrcFile(Filename.fromOsSpecific(prcFile)) removeDecls = [] for dec in range(page.getNumDeclarations()): # Check if our variables are given. # NOTE: This check has to be done to not loose our base or other # manual config changes by the user if page.getVariableName(dec) in customConfigVariables: decl = page.modifyDeclaration(dec) removeDecls.append(decl) for dec in removeDecls: page.deleteDeclaration(dec) # NOTE: audio-mute are custom variables and # have to be loaded by hand at startup # audio page.makeDeclaration("audio-volume", volume) page.makeDeclaration("audio-mute", mute) else: # Create a config file and set default values cpMgr = ConfigPageManager.getGlobalPtr() page = cpMgr.makeExplicitPage("%s Pandaconfig" % appName) # set OpenGL to be the default page.makeDeclaration("load-display", "pandagl") # get the displays width and height w = self.pipe.getDisplayWidth() h = self.pipe.getDisplayHeight() # set the window size in the config file page.makeDeclaration("win-size", "%d %d" % (w, h)) # set the default to fullscreen in the config file page.makeDeclaration("fullscreen", "1") # audio page.makeDeclaration("audio-volume", volume) page.makeDeclaration("audio-mute", "#f") # create a stream to the specified config file configfile = OFileStream(prcFile) # and now write it out page.write(configfile) # close the stream configfile.close()