def __init__(self, nodePath, lookAtNode, durationFactor=0.01, name=None, blendType='noBlend', bakeInStart=1, fluid=0, other=None, isBackwards=False): if not nodePath.isEmpty(): _oldHpr = nodePath.getHpr() #if isBackwards: # _oldHpr.setX(_oldHpr.getXy()[0] - 180) nodePath.headsUp(lookAtNode) #if isBackwards: # nodePath.setH(nodePath.getH() - 180) _newHpr = nodePath.getHpr() nodePath.setHpr(_oldHpr) _distance = (_newHpr.getXy() - _oldHpr.getXy()).length() self.distance = _distance duration = _distance * durationFactor LerpQuatInterval.__init__(self, nodePath, duration, _newHpr, startHpr=_oldHpr, other=other, blendType=blendType, bakeInStart=bakeInStart, fluid=fluid, name=name) else: self.notify.warning('You must specify a non-empty NodePath!')
def move_and_rotate_camera_to(self, new_pos, new_rot, absolute=True, duration=0): if settings.debug_jump: duration = 0 if duration == 0: if absolute: self.camera.set_camera_pos(new_pos) self.camera.set_camera_rot(new_rot) else: self.camera.set_rel_camera_pos(new_pos) self.camera.set_rel_camera_rot(new_rot) else: if self.current_interval != None: self.current_interval.pause() self.fake = NodePath('fake') if absolute: self.start_pos = self.camera.get_rel_camera_pos() self.end_pos = self.camera.get_rel_position_of(new_pos) #TODO #new_rot = self.camera.get_rel_rotation_of(new_pos) nodepath_lerp = LerpQuatInterval(self.fake, duration=duration, blendType='easeInOut', quat = LQuaternion(*new_rot), startQuat = LQuaternion(*self.camera.get_camera_rot()) ) func_lerp = LerpFunc(self.do_camera_move_and_rot, fromData=0, toData=1, duration=duration, blendType='easeInOut', name=None) parallel = Parallel(nodepath_lerp, func_lerp) self.current_interval = parallel self.current_interval.start()
def _move(): if self.camera_lerp: self.camera_lerp.pause() # perform movement on target self.camera_target.set_quat( self.camera_target, movement, ) # round to nearest right angle self.camera_target.set_hpr(*[ round(axis / 90.0) * 90 for axis in self.camera_target.get_hpr() ]) # start lerping self.camera_lerp = LerpQuatInterval( self.camera_pivot, 1.0, self.camera_target.get_quat(), blendType='easeOut', ) self.camera_lerp.start()
class Laserwurfel(ShowBase): def __init__(self): ShowBase.__init__(self) self.drawMain() # global music global music music = base.loader.loadSfx(ASSET + "music/menu.ogg") music.setLoop(True) music.setVolume(0.5) print(music.getVolume()) music.play() base.setBackgroundColor(0.1, 0.1, 0.1) global playMusic playMusic = True def startGame(self, num): # self.render.set_antialias(p.AntialiasAttrib.M_auto) self.disableMouse() self.mouse_picker = Picker(self) self.initial_node = None self.end_node = None self.level = level.Level() self.cube = self.loader.loadModel(ASSET + 'models/game_elements/cube') self.cube.set_name('Planet') self.cube.reparent_to(self.render) self.nodes = [ [ [ Node(x, y, z, self) if [x, y, z].count(0) < 2 else None for z in [-1, 0, 1] ] for x in [-1, 0, 1]] for y in [-1, 0, 1]] sun = DirectionalLight('sun') sun.set_color(VBase4(0.8, 0.8, 0.5, 1.0)) self.sun = self.render.attach_new_node(sun) self.sun.set_hpr(-45, -45, 0) self.render.set_light(self.sun) fill = DirectionalLight('fill') fill.set_color(VBase4(0.5, 0.5, 0.8, 1.0)) self.fill_light = self.render.attach_new_node(fill) self.fill_light.set_hpr(135, 45, 0) self.render.set_light(self.fill_light) ambient = AmbientLight("ambient") ambient.set_color(VBase4(0.2, 0.2, 0.2, 1.0)) self.ambient = self.render.attach_new_node(ambient) self.render.set_light(self.ambient) self.camera_target = self.render.attach_new_node('camera-target') self.camera_pivot = self.render.attach_new_node("camera-pivot") self.camera.reparent_to(self.camera_pivot) self.camera.set_pos(0, -50, 0) self.camera_lerp = None def _place_facing_helper(x, z): helper = self.camera_pivot.attach_new_node('facing-helper') helper.set_pos(x, -1, z) return helper self.facing_helper = [ [ _place_facing_helper(x, z) for x in [-1, 0, 1]] for z in [-1, 0, 1]] # Mouse self.accept("mouse1", self.OnLeftDown) self.last_click = None self.taskMgr.add(self.mouse_drag_task, "MouseDragTask") self.SetKeybindings() # TODO: Do not hard code level number self.LoadLevel(num) self.introDialoge(num) def drawMain(self): myFrame = DirectFrame(frameColor=(0, 0, 0.30, 1), frameSize=(-1.75, 1.75, -1, 1), pos=(0,0,0)) v = [0] bk_text = "LASERWURFEL" textObject = OnscreenText(text = bk_text, pos = (0,0.8), scale = 0.2,fg=(1,1,1,1),align=TextNode.ACenter,mayChange=1, parent=myFrame) def switchCamp(): self.drawCampaign() myFrame.destroy() def switchSettings(): self.drawSettings() myFrame.destroy() def quit(): sys.exit() #resume = DirectButton(text = ("Resume last saved game"), scale=.05, command=switchCamp, pos=(0,0,0.5), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) campaign = DirectButton(text = ("Campaign"), scale=.05, command=switchCamp, pos=(0,0,0.25), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) settings = DirectButton(text = ("Settings"), scale=.05, command=switchSettings, pos=(0,0,0), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) quit = DirectButton(text = ("Quit"), scale=.05, command=quit, pos=(0,0,-0.25), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) def drawCampaign(self): v = [0] yPos = 0.5 xDivider = 0; myFrame = DirectFrame(frameColor=(0, 0, 0.30, 1), frameSize=(-1.75, 1.75, -1, 1) ,pos=(0,0,0)) bk_text = "Campaign" textObject = OnscreenText(text = bk_text, pos = (0,0.8), scale = 0.2,fg=(1,1,1,1),align=TextNode.ACenter,mayChange=1, parent=myFrame) def chooseLevel(num): self.current_level = num self.startGame(num) music.stop() myFrame.destroy() def switchMain(): self.drawMain() myFrame.destroy() for x in range(1, 21): if(x % 9 == 0 and x > 0): yPos -= 0.5 xDivider = 0 xPos = -1 + (xDivider/4.0) xDivider += 1 available = int(config.parser.items("Levels")[0][1]) if x <= available: state = DGG.NORMAL color = (0, 1, 0, 1) else: state = DGG.DISABLED color = (1, 0, 0, 1) DirectButton( text=("Level " + repr(x)), scale=.05, command=chooseLevel, extraArgs=[x], pos=(xPos, 0, yPos), parent=myFrame, frameSize=(-2, 2, -1.5, 1.9), frameColor=color, state=state ) returnToMenu = DirectButton(text = ("Return to main menu"), scale=.05, command=switchMain, pos=(0,0,-0.8), parent=myFrame, frameSize=(-22, 22, -1.5, 1.9)) def introDialoge(self, num): dsf1=self.mkdsf() dsf1.setPos(0,0,0) t1=OnscreenText(parent=dsf1.getCanvas(), pos=(1,0), scale=.05, wordwrap=35) t1['text'] = self.LoadStory(num)['intro'] def closeWindow(): dsf1.destroy() btn_continue = DirectButton(text = ("Continue"), scale=.05, parent=dsf1.getCanvas(), frameSize=(-3, 3, -1.5, 1.9), pos=(1,0,-2.7), command=closeWindow) def outroDialoge(self): dsf1 = self.mkdsf() dsf1.setPos(0, 0, 0) t1 = OnscreenText( parent=dsf1.getCanvas(), pos=(1, 0), scale=.05, wordwrap=35 ) t1['text'] = self.LoadStory(1)['outro'] def closeWindow(): dsf1.destroy() available = int(config.parser.items("Levels")[0][1]) if available == self.current_level: config.parser.set("Levels", "available", str(available + 1)) config.write() self.closeLevel() DirectButton( text=("Continue"), scale=.05, parent=dsf1.getCanvas(), frameSize=(-3, 3, -1.5, 1.9), pos=(1, 0, -2.7), command=closeWindow ) def mkdsf(self): size = (0.15, 0.15) bgcol=(.2, .2, .2, .5) scrollbarw=0.05 borderw=(0.01,0.01) return DirectScrolledFrame( frameSize=(-1 ,1,-1,1), canvasSize=(-0, 0, -3, .1), borderWidth=borderw, scrollBarWidth=scrollbarw, scale=1, ) def drawSettings(self): myFrame = DirectFrame(frameColor=(0, 0, 0.30, 1), frameSize=(-1.75, 1.75, -1, 1) ,pos=(0,0,0)) bk_text = "Settings" textObject = OnscreenText(text = bk_text, pos = (0,0.8), scale = 0.2,fg=(1,1,1,1),align=TextNode.ACenter,mayChange=1, parent=myFrame) def switchMain(): self.drawMain() myFrame.destroy() def switchAudio(): self.drawAudio() myFrame.destroy() def reset(): self.drawReset() myFrame.destroy() def drawButtons(): audio = DirectButton(text = ("Audio"), scale=.05, command=switchAudio, pos=(0,0,0.5), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) controls = DirectButton(text = ("Controls"), scale=.05, command=reset, pos=(0,0,0.25), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) resetGame = DirectButton(text = ("Reset game"), scale=.05, command=reset, pos=(0,0,0), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) credits = DirectButton(text = ("Credits"), scale=.05, command=reset, pos=(0,0,-0.25), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) returnToMenu = DirectButton(text = ("Return to main menu"), scale=.05, command=switchMain, pos=(0,0,-0.5), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) drawButtons() def drawReset(self): myFrame = DirectFrame(frameColor=(0, 0, 0.30, 1), frameSize=(-1.75, 1.75, -1, 1) ,pos=(0,0,0)) def resetGame(arg): if(arg): print('reset') else: print('nothing') myFrame.destroy() self.drawSettings() dialog = YesNoDialog(dialogName="YesNoCancelDialog", text="Erase your progress?", command=resetGame, parent=myFrame) def drawAudio(self): myFrame = DirectFrame(frameColor=(0, 0, 0.30, 1), frameSize=(-1.75, 1.75, -1, 1) ,pos=(0,0,0)) bk_text = "Audio Settings" textObject = OnscreenText(text = bk_text, pos = (0,0.8), scale = 0.2,fg=(1,1,1,1),align=TextNode.ACenter,mayChange=1, parent=myFrame) def switchSettings(): self.drawSettings() myFrame.destroy() def setVolume(): music.setVolume(volume['value']) print(volume['value']) print('Volume set') def turnAudio(): global playMusic if(turnAudioControl['text'] == "Turn Music Off"): turnAudioControl['text'] = "Turn Music On" print('Audio turned off') music.stop() global playMusic playMusic = False else: turnAudioControl['text'] = "Turn Music Off" music.setLoop(True) music.play() playMusic = True print('Audio turn') ''' if sound.status() == sound.PLAYING: print('Audio turned off') sound.stop() else: sound.setLoop(True) sound.play() ''' volume = DirectSlider(range=(0,1), value=.5, pageSize=3, command=setVolume, pos=(0,0,0.5), parent=myFrame) turnAudioControl = DirectButton(text = ("Turn Music Off"), scale=.05, command=turnAudio, pos=(0,0,0.25), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) returnToMenu = DirectButton(text = ("Return to main menu"), scale=.05, command=switchSettings, pos=(0,0,-0.5), parent=myFrame, frameSize=(-20, 20, -1.5, 1.9)) def quit(self, event=None): self.onDestroy(event) try: base except NameError: sys.exit() base.userExit() def SetKeybindings(self): # Keyboard actions = { "topleft": self.OnTopLeft, "topcenter": self.OnTopCenter, "topright": self.OnTopRight, "middleleft": self.OnMiddleLeft, "middleright": self.OnMiddleRight, "bottomleft": self.OnBottomLeft, "bottomcenter": self.OnBottomCenter, "bottomright": self.OnBottomRight, "rotleft": self.OnRotLeft, "rotright": self.OnRotRight, "rotup": self.OnRotUp, "rotdown": self.OnRotDown, "rotclock": self.OnRotClock, "rotcounterclock": self.OnRotCounterClock } keys = [] duplicates = [] items = config.parser.items("Controls") for item in items: for key in item[1].split(","): if key in keys: duplicates.append(key) keys.append(key) for item in items: for key in item[1].split(","): if key not in duplicates: action = actions[item[0]]() if item[0].startswith('rot'): action = self.move_camera(action) else: action = self.select_node(action) self.accept(key, action) self.accept("escape", self.closeLevel) def move_camera(self, movement): def _move(): if self.camera_lerp: self.camera_lerp.pause() # perform movement on target self.camera_target.set_quat( self.camera_target, movement, ) # round to nearest right angle self.camera_target.set_hpr(*[ round(axis / 90.0) * 90 for axis in self.camera_target.get_hpr() ]) # start lerping self.camera_lerp = LerpQuatInterval( self.camera_pivot, 1.0, self.camera_target.get_quat(), blendType='easeOut', ) self.camera_lerp.start() return _move def select_node(self, position): def _select(): if False in [a % 90 == 0 for a in self.camera_pivot.get_hpr()]: return helper = self.facing_helper[position[1]+1][position[0]+1] [x, y, z] = [ int(round(i)) for i in helper.get_pos(self.render) ] node = self.nodes[x+1][y+1][z+1] if node.is_disabled: return self.OnNodeSelected(node) return _select def OnRotLeft(self): return Quat( +math.sqrt(0.5), +0, +0, -math.sqrt(0.5), ) def OnRotRight(self): return Quat( +math.sqrt(0.5), +0, +0, +math.sqrt(0.5), ) def OnRotUp(self): return Quat( +math.sqrt(0.5), -math.sqrt(0.5), +0, +0, ) def OnRotDown(self): return Quat( +math.sqrt(0.5), +math.sqrt(0.5), +0, +0, ) def OnRotClock(self): return Quat( +math.sqrt(0.5), +0, +math.sqrt(0.5), +0, ) def OnRotCounterClock(self): return Quat( +math.sqrt(0.5), +0, -math.sqrt(0.5), +0, ) def OnTopLeft(self): return (-1, 1) def OnTopCenter(self): return (0, 1) def OnTopRight(self): return (1, 1) def OnMiddleLeft(self): return (-1, 0) def OnMiddleRight(self): return (1, 0) def OnBottomLeft(self): return (-1, -1) def OnBottomCenter(self): return (0, -1) def OnBottomRight(self): return (1, -1) def mouse_drag_task(self, task): mw = self.mouseWatcherNode if mw.hasMouse(): x = mw.getMouseX() y = mw.getMouseY() if mw.isButtonDown(MouseButton.one()): self.OnMouseMotion(x, y) return Task.cont def OnLeftDown(self): self.last_click = None def OnMouseMotion(self, x, y): if self.last_click is None: self.last_click = Vec2(x, y) return here = Vec2(x, y) diff = self.last_click - here diff *= 50 self.last_click = here rotation = Quat() rotation.set_hpr( Vec3(diff.x, -diff.y, 0), CS_default, ) self.camera_target.set_quat( self.camera_target, rotation, ) self.camera_pivot.set_quat(self.camera_target.get_quat()) def closeLevel(self): print("CLOSE") self.music_lvl.stop() for node in self.render.getChildren(): node.removeNode() self.render.clearLight() self.drawCampaign() def SetInitialNode(self, node): self.initial_node = node def GetCurrentNode(self): node = self.initial_node while node and node.get_next(): node = node.get_next() return node def UpdateCurrentNode(self): for y in self.nodes: for x in y: for node in x: if node: node.set_current(current=False) node = self.initial_node while node and node.get_next(): node.set_current(current=False) print("NODE", node) node = node.get_next() if not node.is_destination: node.set_current() def OnNodeSelected(self, obj, select=True): if not isinstance(obj, Node): pos = [] for v in obj.getName().split("|")[1].split(","): pos.append(int(v) + 1) node = self.nodes[pos[0]][pos[1]][pos[2]] else: node = obj current_node = self.GetCurrentNode() # Debug information print("----") print("Clicked node:", node.get_position()) if current_node: print("Current:", current_node.get_position()) if node.get_prev(): print("Prev:", node.get_prev().get_position()) print(node.get_next()) if node.get_next(): print("Next:", node.get_next().get_position()) print("Selected:", node.is_selected()) # Actual algorithm if node.is_selected() == select: if not select and node.get_prev(): self.ConnectNodes(node.get_prev(), node, connect=False) node.select(False) else: return if not current_node: print("ERROR: No current node!") return if node is current_node and node.get_is_editable(): if node.get_prev(): self.ConnectNodes(node.get_prev(), node, connect=False) node.select(select) else: print("Cliked", node.is_selected(), node.get_is_editable()) if node.is_selected(): if node.get_is_editable(): self.ConnectNodes(node.get_prev(), node, connect=False) node.select(select) elif select: if self.ConnectNodes(current_node, node): node.select(select) # Debug information print("~~ NEW ~~") current_node = self.GetCurrentNode() if current_node: print("Current:", current_node.get_position()) if node.get_prev(): print("Prev:", node.get_prev().get_position()) if node.get_next(): print("Next:", node.get_next().get_position()) print("Selected:", node.is_selected()) self.UpdateCurrentNode() self.CheckWin() def CheckWin(self): win = True for w in self.nodes: for x in w: for y in x: if y and y.model: if not y.is_selected(): win = False if win: self.OnWin() def OnWin(self): print("~~~~~~ YOU WON THE LEVEL ~~~~~~~") self.outroDialoge() def ConnectNodes(self, node1, node2, connect=True): print("Connect", node1, node2, connect) if not connect: node2 = None else: for grid in node1.grids: if node2 in grid.nodes: return False if node1.is_destination: return False string_info = self.NodeInLooseString(node2) print(string_info) if node2.is_destination: if node2.get_prev(): return False if string_info["between"]: return False if string_info["last"]: self.ReverseString(node2) if node2.teleport_to: node1.connect_to(node2) node2.connect_to(node2.teleport_to) return True node1.connect_to(node2) if node1.teleport_to and not node2: self.ConnectNodes(node1.get_prev(), node1, connect=False) # TODO: Prevent illegal connections return True def ReverseString(self, node): while node: prev_node = node.get_prev() if node.laser: node.laser.removeNode() node.prev_node = node.next_node node.next_node = prev_node node = prev_node def NodeInLooseString(self, node): if not node: return False goes_to_end = False goes_to_start = False is_first = False is_last = False is_between = False next_node = node.get_next() prev_node = node.get_prev() if not next_node: is_last = True if not prev_node: is_first = True if not (is_first or is_last): is_between = True while next_node: if next_node is self.end_node: goes_to_end = True next_node = next_node.get_next() while prev_node: if prev_node is self.initial_node: goes_to_start = True prev_node = prev_node.get_prev() if (next_node or prev_node): string = True else: string = False return { "loose": not (goes_to_start or goes_to_end), "first": is_first, "last": is_last, "between": is_between, "string": string } def LoadStory(self, number): level_path_intro = path.join(LEVELS, "level" + str(number), "intro") level_path_outro = path.join(LEVELS, "level" + str(number), "outro") print(level_path_intro) intro = open(level_path_intro).read() outro = open(level_path_outro).read() return { "intro": intro, "outro": outro } def LoadLevel(self, number): level_path = path.join(LEVELS, "level" + str(number), "full") self.level.parse(level_path) # Structure for line in self.level.structure: # print(line[0].__name__) if line[0].__name__ == "path": initial_node = self.GetNode(line[1]) initial_node.select(True) initial_node.is_editable = False initial_node.set_current() self.initial_node = initial_node end_node = self.GetNode(line[2]) end_node.setup_model('game_elements/cannon') end_node.is_destination = True self.end_node = end_node elif (line[0].__name__ == "deactivate" and type(line[1][0]) is not str): node = self.GetNode(line[1]) node.model.removeNode() node.is_disabled = True elif line[0].__name__ == "wall": node1 = self.GetNode(line[1]) node2 = self.GetNode(line[2]) grid = Grid(node1, node2, self) switches = [] for i in range(len(line)): if i <= 2 or i % 2 != 1: continue j = i + 1 switch = Switch( self.GetNode(line[i]), self.GetNode(line[i+1]), self) switches.append(switch) grid.switches.append(switches) node1.grids.append(grid) node2.grids.append(grid) elif line[0].__name__ == "teleporter": node1 = self.GetNode(line[1]) node2 = self.GetNode(line[2]) node1.setup_model('game_elements/teleporter') node2.setup_model('game_elements/teleporter') node1.teleport_to = node2 node2.teleport_to = node1 # Decorations i = 1 j = 1 def flip(): flip = random.randint(0, 1) if flip == 1: return True else: return False sides = ["front", "left", "back", "right", "top", "bottom"] for side in sides: animal = "dog" if flip(): animal = "rabbit" for line in self.level.detail[side]: for element in line: model_name = None version = "a" if flip(): version = "b" if element == "@@": model_name = "tree_" + version elif element == "##": model_name = "wheat" elif element == "%%": model_name = animal + "_" + version elif element == "[]": model_name = "house_" + version if model_name: model = self.loader.loadModel( ASSET + "models/decorations/" + model_name) # TODO: Random orientation d = 0 if side == "front": model.set_hpr(d, 90, 0) model.set_pos(j - 5, -4.5, i - 5) elif side == "left": model.set_hpr(d, -90, -90) model.set_pos(-4.5, j - 5, i - 5) elif side == "back": model.set_hpr(d, -90, 0) model.set_pos(i - 5, 4.5, j - 5) elif side == "right": model.set_hpr(d, -90, 90) model.set_pos(4.5, j - 5, i - 5) elif side == "top": model.set_pos(j - 5, i - 5, 4.5) elif side == "bottom": model.set_hpr(d, -180, 0) model.set_pos(j - 5, i - 5, -4.5) model.reparent_to(self.cube) if j < 9: j += 1 else: j = 1 if i < 9: i += 1 else: i = 1 # Meta self.music_lvl = self.loader.loadSfx( ASSET + 'music/' + self.level.meta["track"][1]) self.music_lvl.setLoop(True) print(music.getVolume()) self.music_lvl.setVolume(music.getVolume()) if playMusic: self.music_lvl.play() def GetNode(self, pos): node = self.nodes[pos[0] + 1][pos[1] + 1][pos[2] + 1] return node def GetPositionBetweenNodes(self, node1, node2): vecA = [n * 4.5 for n in node1.position] vecB = [n * 4.5 for n in node2.position] vecAB = [n / 2 for n in map(operator.sub, vecB, vecA)] return [map(operator.add, vecA, vecAB), vecA]