class Game(): def __init__(self, _parent=None): self.parent = _parent # Containers self.game_objects = {} self.game_doors = {} self.game_objects_np = render.attachNewNode("Game_Objects") self.game_doors_np = render.attachNewNode("Player_Doors") self.game_doors_np.setPos(0, 0, 0) self.game_counter_node = None self.game_collector_nodes = [] self.redDudesCount = 0 self.blueDudesCount = 0 # Physics world self.physics_world = None self.builder = Builder(self) # level lights self.directLight = None # Dude class self.dude = None self.spawnPoints = self.builder.spawnPoints # HUD self.hud = Hud() # Lightshow self.elapsed = 0.0 def start(self, levelID, winCondition=25): self.winCondition = winCondition self.loadLevel("assets/level{}".format(levelID)) self.loadLights() # player self.loadPlayer("default") self.loadDude() # Timer taskMgr.add(self.update, "Game_Update_Task", 0) self.hud.show() # start the Lightshow taskMgr.add(self.discoLightTask, "the lightshow") def stop(self): self.player.stop() self.dude.stop() self.builder.cleanup() self.physics_world = None render.clearLight() self.directLight = None self.hud.hide() taskMgr.remove("the lightshow") def update(self, task): if self.game_counter_node is None: return ghost = self.game_counter_node.node() for node in ghost.getOverlappingNodes(): if "red" in node.name: self.redDudesCount += 1 self.physics_world.removeRigidBody(self.dude.dudes[node.name].node()) self.dude.dudes[node.name].removeNode() self.hud.update(self.redDudesCount, self.blueDudesCount) del self.dude.dudes[node.name] break elif "blue" in node.name: self.blueDudesCount += 1 self.physics_world.removeRigidBody(self.dude.dudes[node.name].node()) self.dude.dudes[node.name].removeNode() self.hud.update(self.redDudesCount, self.blueDudesCount) del self.dude.dudes[node.name] break if self.redDudesCount > self.blueDudesCount: base.messenger.send("lostGame") return Task.done elif self.blueDudesCount >= self.winCondition: base.messenger.send("wonGame") return Task.done for collectorGhostNP in self.game_collector_nodes: collectorGhost = collectorGhostNP.node() for node in collectorGhost.getOverlappingNodes(): if "red" in node.name: self.physics_world.removeRigidBody(self.dude.dudes[node.name].node()) self.dude.dudes[node.name].removeNode() self.hud.update(self.redDudesCount, self.blueDudesCount) del self.dude.dudes[node.name] return Task.cont def setPhysicsWorld(self, _physicsworld): self.physics_world = _physicsworld #### LOADERS #### def loadLevel(self, _filename): self.builder.parseEggFile(_filename) def loadLights(self): # Set a simple light dlight = DirectionalLight('DirectLight') dlnp = render.attachNewNode(dlight) dlnp.setHpr(-30, 0, 0) render.setLight(dlnp) self.directLight = dlnp self.discoLights = [] p1 = PointLight("PointLight1") p1.setColor(VBase4(1, 0, 0, 1)) p1.setAttenuation((0.08, 0, 0.05)) p1np = render.attachNewNode(p1) p1np.setPos(0, -5, 0) render.setLight(p1np) self.discoLights.append(p1) p2 = PointLight("PointLight2") p2.setColor(VBase4(0, 1, 0, 1)) p2.setAttenuation((0.08, 0, 0.05)) p2np = render.attachNewNode(p2) p2np.setPos(5, -5, 0) render.setLight(p2np) self.discoLights.append(p2) p3 = PointLight("PointLight3") p3.setColor(VBase4(0, 0, 1, 1)) p3.setAttenuation((0.08, 0, 0.05)) p3np = render.attachNewNode(p3) p3np.setPos(-5, -5, 0) render.setLight(p3np) self.discoLights.append(p3) p4 = PointLight("PointLight4") p4.setColor(VBase4(0, 0, 1, 1)) p4.setAttenuation((0.08, 0, 0.05)) p4np = render.attachNewNode(p4) p4np.setPos(-5, -5, 5) render.setLight(p4np) self.discoLights.append(p4) p5 = PointLight("PointLight1") p5.setColor(VBase4(0, 0, 1, 1)) p5.setAttenuation((0.08, 0, 0.05)) p5np = render.attachNewNode(p5) p5np.setPos(0, -5, 5) render.setLight(p5np) self.discoLights.append(p5) p6 = PointLight("PointLight1") p6.setColor(VBase4(0, 0, 1, 1)) p6.setAttenuation((0.08, 0, 0.05)) p6np = render.attachNewNode(p6) p6np.setPos(5, -5, 5) render.setLight(p6np) self.discoLights.append(p6) def discoLightTask(self, task): self.elapsed += globalClock.getDt() if self.elapsed > 0.75: for light in self.discoLights: newcolor = choice( [VBase4(0, 0, 1, 1), VBase4(0, 1, 0, 1), VBase4(1, 0, 0, 1), VBase4(0, 1, 1, 1), VBase4(1, 0, 1, 1), VBase4(1, 1, 0, 1),] ) light.setColor(newcolor) self.elapsed = 0.0 return task.cont def loadPlayer(self, _name): self.player = Player(self) self.player.start() def loadDude(self): self.dude = Dude(self) self.dude.start()
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) # shader generator render.setShaderAuto() # # 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() # check if particles should be enabled particles = ConfigVariableBool("particles-enabled", True).getValue() if particles: self.enableParticles() # check if the config file hasn't been created if not os.path.exists(prcFile): # 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) elif base.appRunner: # As when the application is started as appRunner instance # it doesn't respect our loadPrcFile configurations specific # to the window, hence we need to manually set them here. for dec in range(mainConfig.getNumDeclarations()): #TODO: Check for all window specific variables like # fullscreen, screen size, title and window # decoration that you have in your configuration # and set them by your own. if mainConfig.getVariableName(dec) == "fullscreen": if not mainConfig.getDeclaration(dec).getBoolWord(0): break # 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) break # 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 # base.cTrav = CollisionTraverser("base collision traverser") base.pusher = CollisionHandlerPusher() self.menu = Menu() self.credits = Credits() self.charSelection = CharacterSelection() self.levelSelection = LevelSelection() self.koScreen = KoScreen() self.hud = Hud() self.menuMusic = loader.loadMusic("assets/audio/menuMusic.ogg") self.menuMusic.setLoop(True) self.fightMusic = loader.loadMusic("assets/audio/fightMusic.ogg") self.fightMusic.setLoop(True) base.audio3d = Audio3DManager(base.sfxManagerList[0], camera) # # Event handling # self.accept("escape", self.__escape) # # Start with the menu # self.request("Menu") # # FSM PART # def enterMenu(self): show_cursor() self.accept("Menu-Start", self.request, ["CharSelection"]) self.accept("Menu-Credits", self.request, ["Credits"]) self.accept("Menu-Quit", self.quit) self.ignore("KoScreen-Back") self.koScreen.hide() self.menu.show() if self.menuMusic.status() != AudioSound.PLAYING: self.menuMusic.play() if self.fightMusic.status() == AudioSound.PLAYING: self.fightMusic.stop() def exitMenu(self): self.ignore("Menu-Start") self.ignore("Menu-Credits") self.ignore("Menu-Quit") self.menu.hide() def enterCredits(self): self.accept("Credits-Back", self.request, ["Menu"]) self.koScreen.hide() self.credits.show() def exitCredits(self): self.ignore("Credits-Back") self.credits.hide() def enterCharSelection(self): self.accept("CharSelection-Back", self.request, ["Menu"]) self.accept("CharSelection-Start", self.request, ["LevelSelection"]) self.charSelection.show() def exitCharSelection(self): self.ignore("CharSelection-Start") self.ignore("CharSelection-Back") self.charSelection.hide() self.selectedChar1 = self.charSelection.selectedCharacter1 self.selectedChar2 = self.charSelection.selectedCharacter2 def enterLevelSelection(self): self.accept("LevelSelection-Back", self.request, ["CharSelection"]) self.accept("LevelSelection-Start", self.request, ["Game"]) self.levelSelection.show() def exitLevelSelection(self): self.ignore("LevelSelection-Start") self.ignore("LevelSelection-Back") self.levelSelection.hide() def enterGame(self): # main game code should be called here self.arena = Arena(self.levelSelection.selectedLevel) self.arena.start() self.camera.setPos(0, -5, 1.25) self.player = Player(0, self.selectedChar1, "p1") self.player2 = Player(1, self.selectedChar2, "p2") self.player.setEnemy(self.player2.collisionNodeName) self.player2.setEnemy(self.player.collisionNodeName) self.player.start(self.arena.getStartPos(1)) self.player2.start(self.arena.getStartPos(2)) self.taskMgr.add(self.updateWorldCam, "world camera update task") self.accept("gameOver", self.gameOver) self.hud.show() def lifeChanged(charId, health): base.messenger.send("hud_setLifeBarValue", [charId, health]) self.accept("lifeChanged", lifeChanged) hide_cursor() if self.fightMusic.status() != AudioSound.PLAYING: self.fightMusic.play() if self.menuMusic.status() == AudioSound.PLAYING: self.menuMusic.stop() def exitGame(self): # cleanup for game code self.taskMgr.remove("world camera update task") self.player.stop() self.player2.stop() del self.player del self.player2 self.arena.stop() self.ignore("gameOver") self.ignore("lifeChanged") self.hud.hide() # # FSM PART END # # # BASIC FUNCTIONS # def gameOver(self, LoosingCharId): show_cursor() winningChar = 1 if LoosingCharId == 0: winningChar = 2 self.accept("KoScreen-Back", self.request, ["Credits"]) self.koScreen.show(winningChar) def updateWorldCam(self, task): playerVec = self.player.getPos() - self.player2.getPos() playerDist = playerVec.length() x = self.player.getX() + playerDist / 2.0 self.camera.setX(x) zoomout = False if not self.cam.node().isInView(self.player.getPos(self.cam)): camPosUpdate = -2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) zoomout = True if not self.cam.node().isInView(self.player2.getPos(self.cam)): camPosUpdate = -2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) zoomout = True if not zoomout: if self.camera.getY() < -5: camPosUpdate = 2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) return task.cont def __escape(self): if self.state == "Menu": self.quit() elif self.state == "LevelSelection": self.request("CharSelection") 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 #TODO: get values of configurations here particles = "#f" if not base.particleMgrEnabled else "#t" volume = str(round(base.musicManager.getVolume(), 2)) mute = "#f" if base.AppHasAudioFocus else "#t" #TODO: add any configuration variable name that you have added customConfigVariables = [ "", "particles-enabled", "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: particles-enabled and audio-mute are custom variables and # have to be loaded by hand at startup # Particles page.makeDeclaration("particles-enabled", particles) # 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") # particles page.makeDeclaration("particles-enabled", "#t") # 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()
class Main(ShowBase, FSM): """Main function of the application initialise the engine (ShowBase)""" def __init__(self): """initialise the engine""" ShowBase.__init__(self) base.notify.info("Version {}".format(versionstring)) FSM.__init__(self, "FSM-Game") # # BASIC APPLICATION CONFIGURATIONS # # disable pandas default camera driver self.disableMouse() # set antialias for the complete sceen to automatic self.render.setAntialias(AntialiasAttrib.MAuto) # shader generator render.setShaderAuto() # Enhance font readability DGG.getDefaultFont().setPixelsPerUnit(100) # get the displays width and height for later usage self.dispWidth = self.pipe.getDisplayWidth() self.dispHeight = self.pipe.getDisplayHeight() # # CONFIGURATION LOADING # # load given variables or set defaults # check if particles should be enabled # NOTE: If you use the internal physics engine, this always has # to be enabled! particles = ConfigVariableBool("particles-enabled", True).getValue() if particles: self.enableParticles() def setFullscreen(): """Helper function to set the window fullscreen with width and height set to the screens size""" # 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(self.dispWidth, self.dispHeight) # request the new properties base.win.requestProperties(props) # Set the config variables so we correctly store the # new size and fullscreen setting later winSize = ConfigVariableString("win-size") winSize.setValue("{} {}".format(self.dispWidth, self.dispHeight)) fullscreen = ConfigVariableBool("fullscreen") fullscreen.setValue(True) # Render a frame to make sure the fullscreen is applied # before we do anything else self.taskMgr.step() # make sure to propagate the new aspect ratio properly so # the GUI and other things will be scaled appropriately aspectRatio = self.dispWidth / self.dispHeight self.adjustWindowAspectRatio(aspectRatio) # check if the config file hasn't been created if not os.path.exists(prcFile): setFullscreen() # automatically safe configuration at application exit #base.exitFunc = self.__writeConfig # # INITIALIZE GAME CONTENT # base.cTrav = CollisionTraverser("base collision traverser") base.pusher = CollisionHandlerPusher() self.menu = Menu() self.credits = Credits() self.charSelection = CharacterSelection() self.levelSelection = LevelSelection() self.koScreen = KoScreen() self.hud = Hud() self.menuMusic = loader.loadMusic("assets/audio/menuMusic.ogg") self.menuMusic.setLoop(True) self.fightMusic = loader.loadMusic("assets/audio/fightMusic.ogg") self.fightMusic.setLoop(True) base.audio3d = Audio3DManager(base.sfxManagerList[0], camera) # # EVENT HANDLING # # By default we accept the escape key self.accept("escape", self.__escape) # # ENTER GAMES INITIAL FSM STATE # self.request("Menu") # # FSM PART # def enterMenu(self): show_cursor() self.accept("Menu-Start", self.request, ["CharSelection"]) self.accept("Menu-Credits", self.request, ["Credits"]) self.accept("Menu-Quit", self.userExit) self.ignore("KoScreen-Back") self.koScreen.hide() self.menu.show() if self.menuMusic.status() != AudioSound.PLAYING: self.menuMusic.play() if self.fightMusic.status() == AudioSound.PLAYING: self.fightMusic.stop() def exitMenu(self): self.ignore("Menu-Start") self.ignore("Menu-Credits") self.ignore("Menu-Quit") self.menu.hide() def enterCredits(self): self.accept("Credits-Back", self.request, ["Menu"]) self.koScreen.hide() self.credits.show() def exitCredits(self): self.ignore("Credits-Back") self.credits.hide() def enterCharSelection(self): self.accept("CharSelection-Back", self.request, ["Menu"]) self.accept("CharSelection-Start", self.request, ["LevelSelection"]) self.charSelection.show() def exitCharSelection(self): self.ignore("CharSelection-Start") self.ignore("CharSelection-Back") self.charSelection.hide() self.selectedChar1 = self.charSelection.selectedCharacter1 self.selectedChar2 = self.charSelection.selectedCharacter2 def enterLevelSelection(self): self.accept("LevelSelection-Back", self.request, ["CharSelection"]) self.accept("LevelSelection-Start", self.request, ["Game"]) self.levelSelection.show() def exitLevelSelection(self): self.ignore("LevelSelection-Start") self.ignore("LevelSelection-Back") self.levelSelection.hide() def enterGame(self): # main game code should be called here self.arena = Arena(self.levelSelection.selectedLevel) self.arena.start() self.camera.setPos(0, -5, 1.25) self.player = Player(0, self.selectedChar1, "p1") self.player2 = Player(1, self.selectedChar2, "p2") self.player.setEnemy(self.player2.collisionNodeName) self.player2.setEnemy(self.player.collisionNodeName) self.player.start(self.arena.getStartPos(1)) self.player2.start(self.arena.getStartPos(2)) self.taskMgr.add(self.updateWorldCam, "world camera update task") self.accept("gameOver", self.gameOver) self.hud.show() def lifeChanged(charId, health): base.messenger.send("hud_setLifeBarValue", [charId, health]) self.accept("lifeChanged", lifeChanged) hide_cursor() if self.fightMusic.status() != AudioSound.PLAYING: self.fightMusic.play() if self.menuMusic.status() == AudioSound.PLAYING: self.menuMusic.stop() def exitGame(self): # cleanup for game code self.taskMgr.remove("world camera update task") self.player.stop() self.player2.stop() del self.player del self.player2 self.arena.stop() self.ignore("gameOver") self.ignore("lifeChanged") self.hud.hide() # # FSM PART END # # # BASIC FUNCTIONS # def gameOver(self, LoosingCharId): show_cursor() winningChar = 1 if LoosingCharId == 0: winningChar = 2 self.accept("KoScreen-Back", self.request, ["Credits"]) self.koScreen.show(winningChar) def updateWorldCam(self, task): playerVec = self.player.getPos() - self.player2.getPos() playerDist = playerVec.length() x = self.player.getX() + playerDist / 2.0 self.camera.setX(x) zoomout = False if not self.cam.node().isInView(self.player.getPos(self.cam)): camPosUpdate = -2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) zoomout = True if not self.cam.node().isInView(self.player2.getPos(self.cam)): camPosUpdate = -2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) zoomout = True if not zoomout: if self.camera.getY() < -5: camPosUpdate = 2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) return task.cont def __escape(self): """Handle user escape key klicks""" if self.state == "Menu": # In this state, we will stop the application self.userExit() elif self.state == "LevelSelection": self.request("CharSelection") else: # In every other state, we switch back to the Menu state self.request("Menu") 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 # #TODO: add any configuration variable names that you have added # to the dictionaries in the next lines. Set the current # configurations value as value in this dictionary and it's # name as key. configVariables = { # set the window size in the config file "win-size": ConfigVariableString( "win-size", "{} {}".format(self.dispWidth, self.dispHeight)).getValue(), # set the default to fullscreen in the config file "fullscreen": "#t" if ConfigVariableBool("fullscreen", True).getValue() else "#f", # particles "particles-enabled": "#t" if self.particleMgrEnabled else "#f", # audio "audio-volume": str(round(self.musicManager.getVolume(), 2)), "audio-music-active": "#t" if ConfigVariableBool("audio-music-active").getValue() else "#f", "audio-sfx-active": "#t" if ConfigVariableBool("audio-sfx-active").getValue() else "#f", # logging "notify-output": os.path.join(basedir, "game.log"), # window "framebuffer-multisample": "#t" if ConfigVariableBool("framebuffer-multisample").getValue() else "#f", "multisamples": str(ConfigVariableInt("multisamples", 8).getValue()), "texture-anisotropic-degree": str(ConfigVariableInt("texture-anisotropic-degree").getValue()), "textures-auto-power-2": "#t" if ConfigVariableBool("textures-auto-power-2", True).getValue() else "#f", } page = None # Check if we have an existing configuration file 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 configVariables.keys(): removeDecls.append(page.modifyDeclaration(dec)) for dec in removeDecls: page.deleteDeclaration(dec) else: # Create a config file and set default values cpMgr = ConfigPageManager.getGlobalPtr() page = cpMgr.makeExplicitPage("Application Config") # always write custom configurations for key, value in configVariables.items(): page.makeDeclaration(key, value) # create a stream to the specified config file configfile = OFileStream(prcFile) # and now write it out page.write(configfile) # close the stream configfile.close()
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) # shader generator render.setShaderAuto() # # 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() # check if particles should be enabled particles = ConfigVariableBool("particles-enabled", True).getValue() if particles: self.enableParticles() # check if the config file hasn't been created if not os.path.exists(prcFile): # 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) elif base.appRunner: # As when the application is started as appRunner instance # it doesn't respect our loadPrcFile configurations specific # to the window, hence we need to manually set them here. for dec in range(mainConfig.getNumDeclarations()): #TODO: Check for all window specific variables like # fullscreen, screen size, title and window # decoration that you have in your configuration # and set them by your own. if mainConfig.getVariableName(dec) == "fullscreen": if not mainConfig.getDeclaration(dec).getBoolWord(0): break # 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) break # 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 # base.cTrav = CollisionTraverser("base collision traverser") base.pusher = CollisionHandlerPusher() self.menu = Menu() self.credits = Credits() self.charSelection = CharacterSelection() self.levelSelection = LevelSelection() self.koScreen = KoScreen() self.hud = Hud() self.menuMusic = loader.loadMusic("assets/audio/menuMusic.ogg") self.menuMusic.setLoop(True) self.fightMusic = loader.loadMusic("assets/audio/fightMusic.ogg") self.fightMusic.setLoop(True) base.audio3d = Audio3DManager(base.sfxManagerList[0], camera) # # Event handling # self.accept("escape", self.__escape) # # Start with the menu # self.request("Menu") # # FSM PART # def enterMenu(self): show_cursor() self.accept("Menu-Start", self.request, ["CharSelection"]) self.accept("Menu-Credits", self.request, ["Credits"]) self.accept("Menu-Quit", self.quit) self.ignore("KoScreen-Back") self.koScreen.hide() self.menu.show() if self.menuMusic.status() != AudioSound.PLAYING: self.menuMusic.play() if self.fightMusic.status() == AudioSound.PLAYING: self.fightMusic.stop() def exitMenu(self): self.ignore("Menu-Start") self.ignore("Menu-Credits") self.ignore("Menu-Quit") self.menu.hide() def enterCredits(self): self.accept("Credits-Back", self.request, ["Menu"]) self.koScreen.hide() self.credits.show() def exitCredits(self): self.ignore("Credits-Back") self.credits.hide() def enterCharSelection(self): self.accept("CharSelection-Back", self.request, ["Menu"]) self.accept("CharSelection-Start", self.request, ["LevelSelection"]) self.charSelection.show() def exitCharSelection(self): self.ignore("CharSelection-Start") self.ignore("CharSelection-Back") self.charSelection.hide() self.selectedChar1 = self.charSelection.selectedCharacter1 self.selectedChar2 = self.charSelection.selectedCharacter2 def enterLevelSelection(self): self.accept("LevelSelection-Back", self.request, ["CharSelection"]) self.accept("LevelSelection-Start", self.request, ["Game"]) self.levelSelection.show() def exitLevelSelection(self): self.ignore("LevelSelection-Start") self.ignore("LevelSelection-Back") self.levelSelection.hide() def enterGame(self): # main game code should be called here self.arena = Arena(self.levelSelection.selectedLevel) self.arena.start() self.camera.setPos(0, -5, 1.25) self.player = Player(0, self.selectedChar1, "p1") self.player2 = Player(1, self.selectedChar2, "p2") self.player.setEnemy(self.player2.collisionNodeName) self.player2.setEnemy(self.player.collisionNodeName) self.player.start(self.arena.getStartPos(1)) self.player2.start(self.arena.getStartPos(2)) self.taskMgr.add(self.updateWorldCam, "world camera update task") self.accept("gameOver", self.gameOver) self.hud.show() def lifeChanged(charId, health): base.messenger.send( "hud_setLifeBarValue", [charId, health]) self.accept("lifeChanged", lifeChanged) hide_cursor() if self.fightMusic.status() != AudioSound.PLAYING: self.fightMusic.play() if self.menuMusic.status() == AudioSound.PLAYING: self.menuMusic.stop() def exitGame(self): # cleanup for game code self.taskMgr.remove("world camera update task") self.player.stop() self.player2.stop() del self.player del self.player2 self.arena.stop() self.ignore("gameOver") self.ignore("lifeChanged") self.hud.hide() # # FSM PART END # # # BASIC FUNCTIONS # def gameOver(self, LoosingCharId): show_cursor() winningChar = 1 if LoosingCharId == 0: winningChar = 2 self.accept("KoScreen-Back", self.request, ["Credits"]) self.koScreen.show(winningChar) def updateWorldCam(self, task): playerVec = self.player.getPos() - self.player2.getPos() playerDist = playerVec.length() x = self.player.getX() + playerDist / 2.0 self.camera.setX(x) zoomout = False if not self.cam.node().isInView(self.player.getPos(self.cam)): camPosUpdate = -2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) zoomout = True if not self.cam.node().isInView(self.player2.getPos(self.cam)): camPosUpdate = -2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) zoomout = True if not zoomout: if self.camera.getY() < -5: camPosUpdate = 2 * globalClock.getDt() self.camera.setY(self.camera, camPosUpdate) return task.cont def __escape(self): if self.state == "Menu": self.quit() elif self.state == "LevelSelection": self.request("CharSelection") 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 #TODO: get values of configurations here particles = "#f" if not base.particleMgrEnabled else "#t" volume = str(round(base.musicManager.getVolume(), 2)) mute = "#f" if base.AppHasAudioFocus else "#t" #TODO: add any configuration variable name that you have added customConfigVariables = [ "", "particles-enabled", "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: particles-enabled and audio-mute are custom variables and # have to be loaded by hand at startup # Particles page.makeDeclaration("particles-enabled", particles) # 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") # particles page.makeDeclaration("particles-enabled", "#t") # 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()
class Game(GameBase, FSM): def __init__(self): GameBase.__init__(self, debug=False) FSM.__init__(self, "GUI FSM") base.disableMouse() self.menu = Menu() self.missionScreen = MissionScreen() self.debrief = Debrief() self.hud = Hud() self.missionSelect = MissionSelect() base.camLens.setFov(90) self.setMusic("audio/music.mp3", volume=0.5) self.setMusic("audio/engine1.wav", volume=0.3) self.request("Menu") base.taskMgr.add(self.missionOverTask, "is mission over") def enterMenu(self): self.menu.show() self.accept("menu-start", self.request, ["MissionSelect"]) self.accept("menu-instructions", self.request, ["Instructions"]) self.accept("menu-quit", sys.exit) def exitMenu(self): self.menu.hide() self.ignore("menu-start") self.ignore("menu-instructions") self.ignore("menu-quit") def enterMissionSelect(self): self.missionSelect.show() self.accept("missionselect-m1", self.setMission, ["m1"]) self.accept("missionselect-m2", self.setMission, ["m2"]) self.accept("missionselect-test", self.setMission, ["test"]) def exitMissionSelect(self): self.missionSelect.hide() self.ignore("missionselect-m1") self.ignore("missionselect-m2") def enterMissionScreen(self): self.missionScreen.showWithTitle(self.currentMission.objective) self.accept("mission-start", self.request, ["Game"]) def exitMissionScreen(self): self.missionScreen.hide() self.ignore("mission-start") def enterGame(self): self.world = World(self.currentMission.mapName) self.startTime = "Not yet set - not loaded" #set in self.missionOverTask self.player = Player(self.world) self.accept("player-into-Collision", self.player.reset) self.accept("game-quit", self.request, ["Menu"]) def exitGame(self): self.world.destroy() self.player.model.removeNode() del self.player base.taskMgr.remove("hud update") self.hud.timer.setText("") self.hud.hide() base.taskMgr.remove("update player") self.ignore("game-quit") def enterDebrief(self): self.debrief.show() self.debrief.setTitle(self.currentMission.question, isAnswer=False) self.debrief.setButtons(self.currentMission.options) self.accept("debrief-correct", self.debrief.setTitle, ["Correct"]) self.accept("debrief-wrong", self.debrief.setTitle, ["Wrong"]) self.accept("debrief-back", self.request, ["Menu"]) self.accept("debrief-restart", self.request, ["Game"]) def exitDebrief(self): self.debrief.hide() self.ignore("debrief-correct") self.ignore("debrief-wrong") self.debrief.initialise( ) #clear all settings on it, ie title and buttons, as they are mission specific def setMission(self, name): self.currentMission = missions[name] self.request("MissionScreen") def missionOverTask(self, task): if self.state == "Game" and self.world.loaded and self.startTime == "Not yet set - not loaded": self.startTime = time.time() self.hud.show() self.hud.initialise(self.currentMission.objective, self.currentMission.timeAllowed) base.taskMgr.add(self.hud.hudTask, "hud update") if self.state == "Game" and self.world.loaded: if time.time() - self.startTime > self.currentMission.timeAllowed: self.request("Debrief") return task.cont
class Player(DirectObject): def __init__(self, _main): self.main = _main self.name = "" self.points = 0 self.health = 100.0 self.runSpeed = 1.8 self.keyMap = { "left":False, "right":False, "up":False, "down":False } base.camera.setPos(0,0,0) self.model = loader.loadModel("Player") self.model.find('**/+SequenceNode').node().stop() self.model.find('**/+SequenceNode').node().pose(0) base.camera.setP(-90) self.playerHud = Hud() self.playerHud.hide() self.model.hide() # Weapons: size=2, 0=main, 1=offhand self.mountSlot = [] self.activeWeapon = None self.isAutoActive = False self.trigger = False self.lastShot = 0.0 self.fireRate = 0.0 self.playerTraverser = CollisionTraverser() self.playerEH = CollisionHandlerEvent() ## INTO PATTERNS self.playerEH.addInPattern('intoPlayer-%in') #self.playerEH.addInPattern('colIn-%fn') self.playerEH.addInPattern('intoHeal-%in') self.playerEH.addInPattern('intoWeapon-%in') ## OUT PATTERNS self.playerEH.addOutPattern('outOfPlayer-%in') playerCNode = CollisionNode('playerSphere') playerCNode.setFromCollideMask(BitMask32.bit(1)) playerCNode.setIntoCollideMask(BitMask32.bit(1)) self.playerSphere = CollisionSphere(0, 0, 0, 0.6) playerCNode.addSolid(self.playerSphere) self.playerNP = self.model.attachNewNode(playerCNode) self.playerTraverser.addCollider(self.playerNP, self.playerEH) #self.playerNP.show() self.playerPusher = CollisionHandlerPusher() self.playerPusher.addCollider(self.playerNP, self.model) self.playerPushTraverser = CollisionTraverser() self.playerPushTraverser.addCollider(self.playerNP, self.playerPusher) def acceptKeys(self): self.accept("w", self.setKey, ["up", True]) self.accept("w-up", self.setKey, ["up", False]) self.accept("a", self.setKey, ["left", True]) self.accept("a-up", self.setKey, ["left", False]) self.accept("s", self.setKey, ["down", True]) self.accept("s-up", self.setKey, ["down", False]) self.accept("d", self.setKey, ["right", True]) self.accept("d-up", self.setKey, ["right", False]) # Add mouse btn for fire() self.accept("mouse1", self.setWeaponTrigger, [True]) self.accept("mouse1-up", self.setWeaponTrigger, [False]) # Killed enemies self.accept("killEnemy", self.addPoints) # Game states self.accept("doDamageToPlayer", self.doDamage) def ignoreKeys(self): self.ignore("w") self.ignore("a") self.ignore("s") self.ignore("d") self.ignore("killEnemy") self.ignore("mouse1") self.ignore("mouse1-up") for item in self.main.itemList: if item.type == "heal": self.ignore("intoHeal-" + "itemHeal" + str(item.id)) elif item.type == "gun": self. ignore("intoWeapon-" + "itemWeapon" + str(item.id)) for enemy in self.main.enemyList: self.ignore("intoPlayer-" + "colEnemy" + str(enemy.id)) # Add mouse btn for fire to ignore def setKey(self, action, pressed): self.keyMap[action] = pressed def start(self, startPos, playerName): self.name = playerName self.points = 0 self.health = 100 self.model.reparentTo(render) self.model.setPos(startPos.x, startPos.y, 0) for slot in self.mountSlot[:]: self.mountSlot.remove(slot) # Create a basic weapon self.mountSlot.append(Weapon(self.main, "Pistol", 0.30, 25, weaponType="Pistol")) # Mount the players default weapon self.mountWeapon(self.mountSlot[0]) self.playerHud.setWeapon("Pistol") self.acceptKeys() self.playerHud.show() taskMgr.add(self.move, "moveTask") def stop(self): taskMgr.remove("moveTask") self.ignoreKeys() self.unmountWeapon() self.playerHud.hide() self.model.hide() def addPoints(self, args): self.points += 10 base.messenger.send("setHighscore", [self.points]) def move(self, task): elapsed = globalClock.getDt() #self.playerTraverser.traverse(self.main.enemyParent) #self.playerTraverser.traverse(self.main.itemParent) # set headding pos = self.main.mouse.getMousePos() pos.setZ(0) self.model.lookAt(pos) self.model.setP(-90) # new player position if self.keyMap["up"]: # follow mouse mode #self.model.setZ(self.model, 5 * elapsed * self.runSpeed) # axis move mode self.model.setY(self.model.getY() + elapsed * self.runSpeed) elif self.keyMap["down"]: #self.model.setZ(self.model, -5 * elapsed * self.runSpeed) self.model.setY(self.model.getY() - elapsed * self.runSpeed) if self.keyMap["left"]: # follow mouse mode #self.model.setX(self.model, -5 * elapsed * self.runSpeed) # axis move mode self.model.setX(self.model.getX() - elapsed * self.runSpeed) elif self.keyMap["right"]: #self.model.setX(self.model, 5 * elapsed * self.runSpeed) self.model.setX(self.model.getX() + elapsed * self.runSpeed) # actualize cam position base.camera.setPos(self.model.getPos()) base.camera.setZ(20) return task.cont def mountWeapon(self, _weaponToMount): self.activeWeapon = _weaponToMount # self.mountSlot[0] if self.activeWeapon.style == "TwoHand": self.model.find('**/+SequenceNode').node().pose(0) else: self.model.find('**/+SequenceNode').node().pose(1) self.activeWeapon.model.reparentTo(self.model) self.activeWeapon.model.setY(self.model.getY() - 0.1) self.model.show() self.activeWeapon.model.show() self.fireRate = self.activeWeapon.fireRate def unmountWeapon(self): self.activeWeapon.model.hide() def setWeaponTrigger(self, _state): self.trigger = _state if _state: mpos = self.main.mouse.getMousePos() self.activeWeapon.doFire(mpos) if self.activeWeapon.weaponType == "MG": self.fireActiveWeapon() else: self.activeWeapon.stopFire() else: self.activeWeapon.stopFire() taskMgr.remove("Fire") def fireActiveWeapon(self): if self.activeWeapon: #mpos = self.main.mouse.getMousePos() taskMgr.add(self.fireUpdate, "Fire") #self.activeWeapon.doFire(mpos) def fireUpdate(self, task): dt = globalClock.getDt() self.lastShot += dt mpos = self.main.mouse.getMousePos() #print self.lastShot if self.lastShot >= self.fireRate: self.lastShot -= self.fireRate if self.trigger: self.activeWeapon.doFire(mpos) #task.delayTime += self.fireRate return task.again def setMouseBtn(self): self.trigger = False print "Mouse Released" def addEnemyDmgEvent(self, _id): self.accept("intoPlayer-" + "colEnemy" + str(_id), self.setEnemyAttack) #self.accept("outOfPlayer-" + "colEnemy" + str(_id), self.setEnemyAttackOutOfRange) def setEnemyAttack(self, _entry): enemyColName = _entry.getIntoNodePath().node().getName() base.messenger.send("inRange-" + enemyColName, [True]) def setEnemyAttackOutOfRange(self, _entry): enemyColName = _entry.getIntoNodePath().node().getName() base.messenger.send("inRange-" + enemyColName, [False]) def doDamage(self, _dmg): if self.health <= 0: #print "KILLED IN ACTION" self.main.stop() else: self.health -= _dmg #print "Remaining Health: ", self.health base.messenger.send("setHealth", [self.health]) def addHealItemEvent(self, _id): self.accept("intoHeal-" + "itemHeal" + str(_id), self.healPlayer) def healPlayer(self, _entry): itemColName = _entry.getIntoNodePath().node().getName() if self.health == 100: pass else: self.health += 50 base.messenger.send("into-" + itemColName) if self.health > 100: self.health = 100 print self.health def addWeaponItemEvent(self, _id): self.accept("intoWeapon-" + "itemWeapon" + str(_id), self.changeWeapon) def changeWeapon(self, _entry): itemColName = _entry.getIntoNodePath().node().getName() base.messenger.send("into-" + itemColName) for weapon in self.mountSlot: if weapon.name == "MachineGun": return self.unmountWeapon() self.mountSlot.append(Weapon(self.main, "MachineGun", 0.15, 50, weaponType="MG")) self.playerHud.setWeapon("MG") self.mountWeapon(self.mountSlot[len(self.mountSlot) - 1]) self.activeWeapon.model.show()