def fallAnimation(self, direction="down"): self.movement.disableControl() side_force = 1.7 if direction == "up": force = Vec3(-side_force, 0, 0) dest_hpr = Vec3(0, 0, -90) elif direction == "down": force = Vec3(side_force, 0, 0) dest_hpr = Vec3(0, 0, 90) elif direction == "left": force = Vec3(0, -side_force, 0) dest_hpr = Vec3(0, 90, 0) elif direction == "right": force = Vec3(0, side_force, 0) dest_hpr = Vec3(0, -90, 0) self.setAnimated(True) final_hpr = dest_hpr * 3.0 + Vec3(random(), random(), random()) * 360.0 * 0.0 anim = LerpFunc(self.animateCube, fromData=0, toData=1, duration=1.3, blendType='noBlend', extraArgs=[ self.cube.get_pos(render), Vec3(0), final_hpr, self.cube, force ]) anim.start()
def fadeOutLevel(self, fadeTime=1): """ the level-falls-apart animation. """ tiles = self.levelNode.findAllMatches("=Pos") for tile in tiles: x, y, z = self.getPosFromTile(tile) self.stopAnimatedTile(x, y, True) tile.setPos(x, y, 0) #tile.setHpr(random()*360,random()*360,random()*360) # seq = LerpPosHprInterval(tile,fadeTime+(0.3*fadeTime*random()),(x,y,-15),(random()*360 -180,random()*360-180,random()*360-180), blendType='easeIn') # seq.start() final_hpr = Vec3(random(), random(), random()) * 360.0 force = (Vec3(random(), random(), random()) - 0.5) * 5.0 force.z = 0 seq = LerpFunc(self.tileGravityAnimation, fromData=0, toData=1, duration=1.0, blendType='noBlend', extraArgs=[ tile.get_pos(render), Vec3(0), final_hpr, tile, force ]) tile.setPythonTag("Seq", seq) seq.start()
def zoomOut(self): i = LerpFunc(self.setZoom, fromData=self.ZOOMLEVEL, toData=self.ZOOMLEVEL * 1.3, duration=1.0, blendType="easeInOut") i.start()
def damage(self, amt): self.hp -= amt if self.hp < 0: self.world.garbage.add(self) return def update_color(scaleval): if self.node: self.node.set_color_scale(scaleval, scaleval, scaleval, 1.0) ramp_up = LerpFunc(update_color, fromData=3, toData=1, duration=.2, name=None) ramp_up.start()
def toggleScale(self) : '''a realistic scaling toggle : ''' if not self.realist_scale : init = 0 end = 1 else: init = 1 end = 0 scale = LerpFunc(self.scaleSystem, fromData=init, toData=end, duration=SCALELEN, blendType='easeIn', name='scaling') scale.start()
def play_audio(audio,fadein = 0, volume = 1, loop = False, manager = None): '''plays an AudioSound''' if manager is _voiceMgr: _currentVoices.append(audio) if loop: audio.setLoop(True) if not fadein: audio.setVolume(volume) audio.play() else: interval = LerpFunc(_lerpAdjust, duration = fadein, fromData = 0, toData = volume, extraArgs = [audio], blendType = 'easeOut') _fadeinIntervalTable[audio] = interval _intervals.append(interval) #save the interval in the table so if the audio stops during the interval it can stop the interval first audio.play() interval.start()
def fadeOutLevel(self,fadeTime=1): """ the level-falls-apart animation. """ tiles = self.levelNode.findAllMatches("=Pos") for tile in tiles: x,y,z = self.getPosFromTile(tile) self.stopAnimatedTile(x,y,True) tile.setPos(x,y,0) #tile.setHpr(random()*360,random()*360,random()*360) # seq = LerpPosHprInterval(tile,fadeTime+(0.3*fadeTime*random()),(x,y,-15),(random()*360 -180,random()*360-180,random()*360-180), blendType='easeIn') # seq.start() final_hpr = Vec3(random(), random(), random()) * 360.0 force = (Vec3(random(), random(), random())-0.5) * 5.0 force.z = 0 seq = LerpFunc(self.tileGravityAnimation, fromData=0, toData=1, duration=1.0, blendType='noBlend', extraArgs=[tile.get_pos(render), Vec3(0), final_hpr, tile, force]) tile.setPythonTag("Seq", seq) seq.start()
def destroyTile(self, x, y, task=None): """ fall animation of tile, sets position of tile to -99,-99 """ tile = self.getTileFromPos(x, y) if (tile != None): tile.setTag('Pos', '-99_-99') final_hpr = Vec3(random(), random(), random()) * 360.0 * 0.0 anim = LerpFunc(self.animateTile, fromData=0, toData=1, duration=1.3, blendType='noBlend', extraArgs=[ tile.get_pos(render), Vec3(0), final_hpr, tile, Vec3(1.7, 0, 0) ]) tile.setPythonTag("Seq", anim) anim.start()
def play_audio(audio, fadein=0, volume=1, loop=False, manager=None): '''plays an AudioSound''' if manager is _voiceMgr: _currentVoices.append(audio) if loop: audio.setLoop(True) if not fadein: audio.setVolume(volume) audio.play() else: interval = LerpFunc(_lerpAdjust, duration=fadein, fromData=0, toData=volume, extraArgs=[audio], blendType='easeOut') _fadeinIntervalTable[audio] = interval _intervals.append(interval) #save the interval in the table so if the audio stops during the interval it can stop the interval first audio.play() interval.start()
class RepairPumpingGame(RepairMincroGame): pumpDownSounds = None pumpUpSounds = None pumpGoodSounds = None pumpBadSounds = None def __init__(self, repairGame): self.config = RepairGlobals.Pumping RepairMincroGame.__init__(self, repairGame, 'pumping', PLocalizer.Minigame_Repair_Pumping_Start) def _initVars(self): RepairMincroGame._initVars(self) self.pumpRate = 0.0 self.remainingWater = 1.0 self.chainCount = 0 self.barDirection = UP self.goalIndex = TOP self.currentBarRate = self.config.barStartRange[0] self.hitRange = self.config.hitRange[0] self.barPercent = 0.0 self.failedPercentAndDirection = (-1.0, UP) def _initAudio(self): RepairMincroGame._initAudio(self) if not self.pumpDownSounds: RepairPumpingGame.pumpDownSounds = (loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_DOWN01), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_DOWN02), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_DOWN03)) RepairPumpingGame.pumpUpSounds = (loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_UP01), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_UP02), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_UP03)) RepairPumpingGame.pumpGoodSounds = (loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_GOOD01), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_GOOD02), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_GOOD03), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_GOOD04), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_GOOD05), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_GOOD06)) RepairPumpingGame.pumpBadSounds = (loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_PUMP_BAD),) def _initVisuals(self): RepairMincroGame._initVisuals(self) self.model = loader.loadModel('models/gui/pir_m_gui_srp_pumping_main') self.visual = self.attachNewNode('visual') self.visual.setPos(-0.25, 0.0, 0.074999999999999997) goalTopLoc = self.model.find('**/locator_top') goalTopLoc.reparentTo(self.visual) goalBottomLoc = self.model.find('**/locator_bottom') goalBottomLoc.reparentTo(self.visual) self.goalPositions = (goalBottomLoc.getPos(self), goalTopLoc.getPos(self)) self.greatLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Pumping_Great, text_fg = (0.20000000000000001, 0.80000000000000004, 0.29999999999999999, 1.0), text_pos = (0.0, 0.59999999999999998), text_align = TextNode.ACenter, text_font = PiratesGlobals.getPirateFont(), relief = None, text_shadow = (0.0, 0.0, 0.0, 1.0), scale = (0.080000000000000002, 0.080000000000000002, 0.080000000000000002), pos = (-0.46500000000000002, 0.0, 0.0), parent = self) self.failLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Pumping_Fail, text_fg = (0.80000000000000004, 0.20000000000000001, 0.29999999999999999, 1.0), text_pos = (0.0, 0.59999999999999998), text_align = TextNode.ARight, text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), relief = None, scale = (0.080000000000000002, 0.080000000000000002, 0.080000000000000002), pos = (-0.625, 0.0, 0.0), parent = self) self.shipBackground = self.model.find('**/static_ship_background') self.shipBackground.reparentTo(self.visual) self.waterMeter = self.model.find('**/sprite_waterBottom') self.waterMeter.reparentTo(self.visual) self.waterTop = self.model.find('**/sprite_waterTop') self.waterTop.reparentTo(self.visual) self.waterMeterTopLoc = self.waterMeter.find('**/locator_topOfShipWater') self.pumpBackground = self.model.find('**/pumpBackground') self.pumpBackground.reparentTo(self.visual) self.pumpWaterTop = self.model.find('**/sprite_pumpWaterTop') self.pumpWaterTop.reparentTo(self.visual) self.pumpWaterBottom = self.model.find('**/sprite_pumpWaterBottom') self.pumpWaterBottom.reparentTo(self.visual) self.pumpWaterTopLoc = self.pumpWaterBottom.find('**/locator_topOfPumpWater') self.pumpHandle = self.model.find('**/sprite_handle') self.pumpHandle.reparentTo(self.visual) self.pumpBar = self.model.find('**/static_pump') self.pumpBar.reparentTo(self.visual) self.goalBox = self.model.find('**/sprite_clickField') self.goalBox.reparentTo(self.visual) self.goalBox.setTransparency(1) self.enableGoalBox() self.pumpLine = self.model.find('**/sprite_bar') self.pumpLine.reparentTo(self.visual) self.ghostLine = self.visual.attachNewNode('ghostLine') self.pumpLine.getChild(0).copyTo(self.ghostLine) self.ghostLine.setScale(self.pumpLine.getScale()) self.ghostLine.setColor(1.0, 0.20000000000000001, 0.20000000000000001, 1.0) self.shipForground = self.model.find('**/static_ship_foreground') self.shipForground.reparentTo(self.visual) cm = CardMaker('cardMaker') cm.setFrame(-0.33000000000000002, 0.33000000000000002, 0.0, 1.0) self.goalBox.setZ(self.goalPositions[TOP].getZ()) self.goalBoxStartScale = self.goalBox.getSz() self.enableGoalBox() self.pumpWaterUpLerp = LerpFunc(self.setPumpWater, fromData = -0.10000000000000001, toData = 1.0, duration = 0.5) self.pumpWaterDownLerp = LerpFunc(self.setPumpWater, fromData = 1.0, toData = -0.10000000000000001, duration = 0.5) self.model.removeNode() del self.model def destroy(self): del self.goalPositions self.pumpBar.removeNode() self.pumpLine.removeNode() self.goalBox.removeNode() self.pumpHandle.removeNode() self.waterMeter.removeNode() self.waterTop.removeNode() self.ghostLine.removeNode() self.shipBackground.removeNode() self.shipForground.removeNode() def reset(self): RepairMincroGame.reset(self) self.remainingWater = WATER_LEVEL_START self.chainCount = 0 self.barDirection = UP self.goalIndex = TOP self.barPercent = 0.0 self.failedPercentAndDirection = (-1.0, UP) actualZ = self.goalPositions[BOTTOM].getZ() actualZ -= self.visual.getZ() self.pumpLine.setZ(actualZ) self.setGoalIndex(TOP) self.pumpHandle.setR(ROTATION_MIN) self.waterMeter.setSz(WATER_LEVEL_START) self.waterTop.setZ(self.waterMeterTopLoc.getZ(self.visual)) self.ghostLine.stash() self.setPumpWater(1.0) self.failLabel.stash() self.greatLabel.stash() self.repairGame.gui.setTutorial(self.name) self.repairGame.gui.setTitle(self.name) def setDifficulty(self, difficulty): RepairMincroGame.setDifficulty(self, difficulty) percent = difficulty / self.repairGame.difficultyMax dif = self.config.pumpPowerRange[0] - self.config.pumpPowerRange[1] self.pumpRate = self.config.pumpPowerRange[0] - dif * percent dif = self.config.barStartRange[0] - self.config.barStartRange[1] self.currentBarRate = self.config.barStartRange[0] - dif * percent dif = self.config.hitRange[0] - self.config.hitRange[1] self.hitRange = self.config.hitRange[0] - dif * percent self.goalBox.setSz((self.hitRange / 0.17999999999999999) * self.goalBoxStartScale) def setGoalIndex(self, goalIndex): self.goalIndex = goalIndex self.goalBox.setZ(self, self.goalPositions[goalIndex].getZ()) self.goalBox.setR(180 * (goalIndex - 1)) def resetFail(self): self.failedPercentAndDirection = (-1.0, UP) self.enableGoalBox() self.hideMarkers() def updateTask(self, task): dt = globalClock.getDt() percentTimeThisStep = dt / (self.currentBarRate + self.config.barSpeedMax) self.barPercent = self.barPercent + percentTimeThisStep * self.barDirection if self.failedPercentAndDirection[0] >= 0.0: if self.failedPercentAndDirection[1] != self.barDirection: if self.failedPercentAndDirection[0] * self.barDirection < self.barPercent * self.barDirection: self.resetFail() if self.barPercent >= 1.0: self.barPercent = 1.0 self.barDirection = DOWN if not self.isLineInBox(): self.chainCount = 0 if self.failedPercentAndDirection[0] < 0.5: self.resetFail() elif self.barPercent <= 0.0: self.barPercent = 0.0 self.barDirection = UP if not self.isLineInBox(): self.chainCount = 0 if self.failedPercentAndDirection[0] > 0.5: self.resetFail() actualZ = self.goalPositions[0].getZ() + (self.goalPositions[1].getZ() - self.goalPositions[0].getZ()) * self.barPercent actualZ -= self.visual.getZ() self.pumpLine.setZ(actualZ) return Task.cont def enableGoalBox(self): self.goalBox.setColor(0.20000000000000001, 1.0, 0.20000000000000001, 0.59999999999999998) self.goalBoxEnabled = 1 def disableGoalBox(self): self.goalBox.setColor(1.0, 0.20000000000000001, 0.20000000000000001, 0.29999999999999999) self.goalBoxEnabled = 0 def isLineInBox(self): if self.goalIndex == TOP: return self.barPercent >= 1.0 - self.hitRange else: return self.barPercent <= self.hitRange def onMouseClick(self): if self.isLineInBox() and self.goalBoxEnabled == 1: actualPumpAmount = self.pumpRate + self.config.chainMultiplier * self.chainCount * self.pumpRate actualPumpAmount *= WATER_LEVEL_START - WATER_LEVEL_DONE self.remainingWater -= actualPumpAmount self.remainingWater = max(0.0, self.remainingWater) self.waterMeter.setSz(self.remainingWater) self.waterTop.setZ(self.waterMeterTopLoc.getZ(self.visual) - 0.001) if self.barPercent > 0.5: self.pumpWaterDownLerp.duration = self.currentBarRate self.pumpWaterDownLerp.start() self.barDirection = DOWN self.pumpHandle.setR(ROTATION_MAX) random.choice(self.pumpDownSounds).play() else: self.pumpWaterUpLerp.duration = self.currentBarRate self.pumpWaterUpLerp.start() self.barDirection = UP self.pumpHandle.setR(ROTATION_MIN) random.choice(self.pumpUpSounds).play() if self.barPercent > 0.5: self.setGoalIndex(BOTTOM) else: self.setGoalIndex(TOP) self.currentBarRate /= self.config.barSpeedIncrease self.chainCount += 1 self.setSuccessMarker() if self.remainingWater <= WATER_LEVEL_DONE and self.barDirection == DOWN: self.remainingWater = 0.0 self.request('Outro') return None totalRange = WATER_LEVEL_START - WATER_LEVEL_DONE current = WATER_LEVEL_START - self.remainingWater percent = min(100, int((current / totalRange) * 100)) self.repairGame.d_reportMincroGameProgress(percent, max(0, min(5, self.chainCount) - 1)) else: self.disableGoalBox() self.currentBarRate /= self.config.barSpeedDecrease self.currentBarRate += (1 - self.config.barSpeedDecrease) * self.config.barSpeedMin self.currentBarRate = min(self.currentBarRate, self.config.barSpeedMin) self.setFailMarker() self.chainCount = 0 self.failedPercentAndDirection = (self.barPercent, self.barDirection) def setPumpWater(self, value): self.pumpWaterBottom.setSz(value) self.pumpWaterTop.setZ(self.pumpWaterTopLoc.getZ(self.visual)) def setSuccessMarker(self): self.greatLabel.setZ(self.pumpLine.getZ()) self.greatLabel.unstash() pumpSoundIndex = min(len(self.pumpGoodSounds) - 1, self.chainCount / 2) self.pumpGoodSounds[pumpSoundIndex].play() def setFailMarker(self): self.hideMarkers() self.ghostLine.setPos(self.pumpLine.getPos()) self.ghostLine.unstash() self.failLabel.setZ(self.pumpLine.getZ()) self.failLabel.unstash() random.choice(self.pumpBadSounds).play() def hideMarkers(self): self.ghostLine.stash() self.greatLabel.stash() self.failLabel.stash() def enterGame(self): RepairMincroGame.enterGame(self) taskMgr.add(self.updateTask, 'RepairPumpingGame.updateTask') self.accept('mouse1', self.onMouseClick) self.enableGoalBox() def exitGame(self): RepairMincroGame.exitGame(self) taskMgr.remove('RepairPumpingGame.updateTask') self.ignore('mouse1') def enterOutro(self): RepairMincroGame.enterOutro(self) self.repairGame.d_reportMincroGameScore(150)
def rotateCube(self, direction): """ rotates the cube according to the direction passed as first argument. accepted values are "up" "down" "left" "right" """ #first check if we are allowed to move the block at all.. if self.isAnimated(): print("canceling rotation of cube") return #cleaning up from last rotation (we cant clean those up at the end of this function cause the interval needs the dummynode for rotation) self.cube.wrtReparentTo(render) try: dummy.remove_node() except: pass self.setAnimated(True) duration = 0.2 x1, y1, x2, y2 = self.getCubeTiles() self.level.animateTile(x1, y1) self.level.animateTile(x2, y2) dummy = render.attachNewNode("dummy") dummy.reparentTo(self.cube) dummy.setZ(render, 0) dummy.wrtReparentTo(render) dummy.setHpr(0, 0, 0) dest_hpr = Vec3(0) if self.cube.getZ(render) > .7: #case1 : cube is standing upright #ok... since we rotate relative there are rounding errors... since there !might! be some uebernoob playing the game #needing one gazillion rotations to reach the goal it might happen those rounding errors actually get visible #so let him enjoy and reset the cube every-time it's standing straight-up. self.cube.setZ( render, 1 ) #how comes this is one?.. well.. i know.. because of my learnings.. self.cube.setX(render, round(self.cube.getX(render), 0)) self.cube.setY(render, round(self.cube.getY(render), 0)) self.cube.setH(render, round(self.cube.getH(render), 0)) self.cube.setP(render, round(self.cube.getP(render), 0)) self.cube.setR(render, round(self.cube.getR(render), 0)) if direction == "right": dummy.setY(dummy, .5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, -90, 0) self.setCubeTiles(x1, y1 + 1, x1, y1 + 2) if direction == "left": dummy.setY(dummy, -.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 90, 0) self.setCubeTiles(x1, y1 - 2, x1, y1 - 1) if direction == "up": dummy.setX(dummy, -.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, -90) self.setCubeTiles(x1 - 2, y1, x1 - 1, y1) if direction == "down": dummy.setX(dummy, .5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, 90) self.setCubeTiles(x1 + 1, y1, x1 + 2, y1) elif x1 == x2: #if aligned to y-axis if direction == "right": dummy.setY(dummy, 1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, -90, 0) self.setCubeTiles(x1, y1 + 2) if direction == "left": dummy.setY(dummy, -1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 90, 0) self.setCubeTiles(x1, y1 - 1) if direction == "up": dummy.setX(dummy, -.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, -90) self.setCubeTiles(x1 - 1, y1, x2 - 1, y2) if direction == "down": dummy.setX(dummy, .5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, 90) self.setCubeTiles(x1 + 1, y1, x2 + 1, y2) elif y1 == y2: #if it is alligned to x-axis.. if direction == "right": dummy.setY(dummy, .5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, -90, 0) self.setCubeTiles(x1, y1 + 1, x2, y2 + 1) if direction == "left": dummy.setY(dummy, -.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 90, 0) self.setCubeTiles(x1, y1 - 1, x2, y2 - 1) if direction == "up": dummy.setX(dummy, -1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, -90) self.setCubeTiles(x1 - 1, y1) if direction == "down": dummy.setX(dummy, 1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, 90) self.setCubeTiles(x1 + 2, y1) else: print("Invalid move. Waiting ..") print("Rotating!") anim = self.animate( LerpHprInterval(dummy, duration, dest_hpr, (0, 0, 0))) #this sorta.. doesnt belong here.. but i dunno where to put it yet. x1, y1, x2, y2 = self.getCubeTiles() # self.level.tintTile(x1,y1) #this is fun to play with if your cube is invisible... # self.level.tintTile(x2,y2) self.level.stopAnimatedTile( x1, y1) #stops the tile-animation for the tiles below the block self.level.stopAnimatedTile(x2, y2) #cheking what consequences your move had... muhahaa... if you get a 1 .. i've got bad news for you checkresult = checkMove(self.level.levelNode, self.getCubeTiles(), self.sounds) if checkresult == 1: self.falls += 1 self.moves += 1 # Force to the corner when the cuboid falls down side_force = 1.7 force = Vec3(0, 0, 0) if direction == "up": force = Vec3(-side_force, 0, 0) elif direction == "down": force = Vec3(side_force, 0, 0) elif direction == "left": force = Vec3(0, -side_force, 0) elif direction == "right": force = Vec3(0, side_force, 0) dummy.set_hpr(render, Vec3(0, 0, 0)) del anim self.setAnimated(True) final_hpr = dest_hpr * 3.0 + Vec3(random(), random(), random()) * 360.0 * 0.0 anim = LerpFunc(self.animateCube, fromData=0, toData=1, duration=1.3, blendType='noBlend', extraArgs=[ dummy.get_pos(render), Vec3(0), final_hpr, dummy, force ]) taskMgr.doMethodLater(anim.getDuration(), self.resetCube, "resetTask") elif checkresult == 2: #ok.. once reached the goal, move the block down, fading it out. thenload the new level etc. anim.pop() anim.append(Func(lambda: self.level.fadeOutLevel())) Sequence(Wait(0.3), Func(lambda *args: self.cube.hide())).start() taskMgr.doMethodLater(anim.getDuration() + 2, self.levelUp, "lvlup") taskMgr.doMethodLater(anim.getDuration() + 2, lambda *args: self.cube.show(), "show cube") taskMgr.doMethodLater( anim.getDuration() + 2, lambda *args: self.shard_node.node().remove_all_children(), "clear shards") Sequence(Wait(0.2), Func(lambda *args: self.sounds.playSound("finish.wav")) ).start() self.moves = 0 self.falls = 0 cube_min, cube_max = Vec3(-0.5, -0.5, -1), Vec3(0.5, 0.5, 1) self.shard_node.set_pos(dummy.get_pos(render) + Vec3(-0.5, 0, 0)) shard_size = (cube_max - cube_min) / 5.0 self.shard_node.hide() Sequence(Wait(0.22), Func(lambda *args: self.shard_node.show())).start() for i in range(5): for j in range(5): for k in range(5): shard = loader.loadModel("models/CubeShard.bam") shard.reparent_to(self.shard_node) shard.set_x(i * shard_size.x + 0.1) shard.set_y(j * shard_size.y + 0.1) shard.set_z(k * shard_size.z + 0.2) shard.set_scale(0.8 + random()) force = Vec3(i - 2 - 0.15, j - 2 - 0.15, k - 2 + 2.6) force.normalize() force *= 12.0 * (1 + random() * 0.5) d_hpr = Vec3(random(), random(), random()) * 360.0 * (3.0 + random()) shard_anim = Sequence( Wait(0.22), LerpFunc(self.animateShard, fromData=0, toData=2, duration=2.0, blendType='noBlend', extraArgs=[ shard.get_pos(), d_hpr, shard, force ]), LerpHprInterval(shard, 1.0 + random(), d_hpr * 1.6, d_hpr, blendType='noBlend'), ) shard_anim.start() elif checkresult == 0: #how lame... just a ..move.. print("playing sound") self.moves += 1 self.sounds.playSound("stonerotate.wav") print("moves:", self.moves, " falls:", self.falls) #last but not least.. we start the animation .. did you know that the pc knows you'r failing before you actually do? .. scary.. anim.start()
class AutoPilot(object): def __init__(self, ui): self.ui = ui self.ship = None self.current_interval = None self.fake = None self.start_pos = LPoint3d() self.end_pos = LPoint3d() def set_ship(self, ship): self.ship = ship def reset(self): if self.current_interval != None: self.current_interval.pause() self.current_interval = None def stash_position(self): self.start_pos = self.ship.get_position_of(self.start_pos) self.end_pos = self.ship.get_position_of(self.end_pos) def pop_position(self): self.start_pos = self.ship.get_rel_position_of(self.start_pos, local=False) self.end_pos = self.ship.get_rel_position_of(self.end_pos, local=False) def do_rot(self, step, origin, delta): #TODO: this is wrong, it should be replaced by do_move_and_rot() rot = origin + delta * step rot.normalize() self.ship.set_rot(rot) if step == 1.0: self.current_interval = None def lookat(self, position, rel=False, duration = 2.0, proportional=True): new_rot, angle = self.ship.calc_look_at(position, rel) if settings.debug_jump: duration = 0 if duration == 0: self.ship.set_rot(new_rot) else: if proportional: duration = duration*angle/pi if self.current_interval != None: self.current_interval.pause() self.current_interval = LerpFunc(self.do_rot, fromData=0, toData=1, duration=duration, blendType='easeInOut', extraArgs=[self.ship.get_rot(), new_rot - self.ship.get_rot()], name=None) self.current_interval.start() def do_move(self, step): position = self.end_pos * step + self.start_pos * (1.0 - step) self.ship.set_frame_pos(position) if step == 1.0: self.current_interval = None def move_to(self, new_pos, absolute=True, duration=0, ease=True): if settings.debug_jump: duration = 0 if duration == 0: if absolute: self.ship.set_pos(new_pos) else: self.ship.set_frame_pos(new_pos) else: if self.current_interval != None: self.current_interval.pause() if absolute: self.start_pos = self.ship.get_frame_pos() self.end_pos = self.ship.get_rel_position_of(new_pos) if ease: blend_type = 'easeInOut' else: blend_type = 'noBlend' self.current_interval = LerpFunc(self.do_move, fromData=0, toData=1, duration=duration, blendType=blend_type, name=None) self.current_interval.start() def do_update_func(self, step, func, extra): delta = globalClock.getRealTime() - self.last_interval_time self.last_interval_time = globalClock.getRealTime() func(delta, *extra) if step == 1.0: self.current_interval = None def update_func(self, func, duration=0, extra=()): if settings.debug_jump: duration = 0 if duration == 0: func(duration, *extra) else: if self.current_interval != None: self.current_interval.pause() self.last_interval_time = globalClock.getRealTime() self.current_interval = LerpFunc(self.do_update_func, fromData=0, toData=1, duration=duration, extraArgs=[func, extra], name=None) self.current_interval.start() def do_move_and_rot(self, step): rot = LQuaterniond(*self.fake.getQuat()) rot.normalize() self.ship.set_frame_rot(rot) position = self.end_pos * step + self.start_pos * (1.0 - step) self.ship.set_frame_pos(position) if step == 1.0: self.current_interval = None def move_and_rotate_to(self, new_pos, new_rot, absolute=True, duration=0): if settings.debug_jump: duration = 0 if duration == 0: if absolute: self.ship.set_pos(new_pos) self.ship.set_rot(new_rot) else: self.ship.set_frame_pos(new_pos) self.ship.set_frame_rot(new_rot) else: if self.current_interval != None: self.current_interval.pause() self.fake = NodePath('fake') if absolute: self.start_pos = self.ship.get_frame_pos() self.end_pos = self.ship.get_rel_position_of(new_pos) start_rot = self.ship.get_frame_rot() end_rot = self.ship.get_rel_rotation_of(new_rot) else: self.start_pos = self.ship.get_frame_pos() self.end_pos = new_pos start_rot = self.ship.get_frame_rot() end_rot = new_rot nodepath_lerp = LerpQuatInterval(self.fake, duration=duration, blendType='easeInOut', quat = LQuaternion(*end_rot), startQuat = LQuaternion(*start_rot) ) func_lerp = LerpFunc(self.do_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 center_on_object(self, target=None, duration=None, cmd=True, proportional=True): if duration is None: duration = settings.fast_move if target is None and self.ui.selected: target=self.ui.selected if target is None: return if cmd: print("Center on", target.get_name()) center = target.get_rel_position_to(self.ship._global_position) self.lookat(center, rel=False, duration=duration, proportional=proportional) def go_system_top(self): if self.ui.nearest_system is not None: distance = self.ui.nearest_system.get_extend() else: distance = units.AU * 4 self.ship.set_pos(LPoint3d(0, 0, distance)) self.lookat(LPoint3d(0, 0, 0)) def go_system_front(self): if self.ui.nearest_system is not None: distance = self.ui.nearest_system.get_extend() else: distance = units.AU * 4 self.ship.set_pos(LPoint3d(0, distance, 0)) self.lookat(LPoint3d(0, 0, 0)) def go_system_side(self): if self.ui.nearest_system is not None: distance = self.ui.nearest_system.get_extend() else: distance = units.AU * 4 self.ship.set_pos(LPoint3d(distance, 0, 0)) self.lookat(LPoint3d(0, 0, 0)) def go_to(self, target, duration, position, direction, up): if up is None: up = LVector3d.up() frame = SynchroneReferenceFrame(target) up = frame.get_orientation().xform(up) if isclose(abs(up.dot(direction)), 1.0): print("Warning: lookat vector identical to up vector") else: # Make the up vector orthogonal to the direction using Gram-Schmidt up = up - direction * up.dot(direction) orientation = LQuaterniond() lookAt(orientation, direction, up) self.move_and_rotate_to(position, orientation, duration=duration) def go_to_front(self, duration = None, distance=None, up=None, star=False): if not self.ui.selected: return target = self.ui.selected if duration is None: duration = settings.slow_move if distance is None: distance = settings.default_distance distance_unit = target.get_apparent_radius() if distance_unit == 0.0: distance_unit = target.get_extend() print("Go to front", target.get_name()) self.ui.follow_selected() center = target.get_rel_position_to(self.ship._global_position) position = None if star: position = target.star else: if target.parent is not None and isinstance(target.parent, SimpleSystem): if target.parent.primary == target: if target.star is not target: position = target.star else: position = target.parent.primary if position is not None: print("Looking from", position.get_name()) position = position.get_rel_position_to(self.ship._global_position) else: position = self.ship.get_pos() direction = center - position direction.normalize() new_position = center - direction * distance * distance_unit self.go_to(target, duration, new_position, direction, up) def go_to_object(self, duration = None, distance=None, up=None): if not self.ui.selected: return target = self.ui.selected if duration is None: duration = settings.slow_move if distance is None: distance = settings.default_distance distance_unit = target.get_apparent_radius() if distance_unit == 0.0: distance_unit = target.get_extend() print("Go to", target.get_name()) self.ui.follow_selected() center = target.get_rel_position_to(self.ship._global_position) direction = center - self.ship.get_pos() direction.normalize() new_position = center - direction * distance * distance_unit self.go_to(target, duration, new_position, direction, up) def go_to_object_long_lat(self, longitude, latitude, duration = None, distance=None, up=None): if not self.ui.selected: return target = self.ui.selected if duration is None: duration = settings.slow_move if distance is None: distance = settings.default_distance distance_unit = target.get_apparent_radius() if distance_unit == 0.0: distance_unit = target.get_extend() print("Go to long-lat", target.get_name()) self.ui.follow_selected() center = target.get_rel_position_to(self.ship._global_position) new_position = (longitude, latitude, distance * distance_unit) new_position = target.spherical_to_cartesian(new_position) direction = center - new_position direction.normalize() self.go_to(target, duration, new_position, direction, up) def go_to_surface(self, duration = None, height=1.001): if not self.ui.selected: return target = self.ui.selected if duration is None: duration = settings.slow_move print("Go to surface", target.get_name()) self.ui.sync_selected() center = target.get_rel_position_to(self.ship._global_position) direction = self.ship.get_pos() - center new_orientation = LQuaterniond() lookAt(new_orientation, direction) height = target.get_height_under(self.ship.get_pos()) + 10 * units.m new_position = center + new_orientation.xform(LVector3d(0, height, 0)) self.move_and_rotate_to(new_position, new_orientation, duration=duration) def go_pole(self, target, lat, duration, zoom): if not self.ui.selected: return target = self.ui.selected if zoom: distance = settings.default_distance else: distance_unit = target.get_apparent_radius() if distance_unit == 0.0: distance_unit = target.get_extend() distance = target.distance_to_obs / distance_unit self.go_to_object_long_lat(0, lat, duration, distance) def go_north(self, duration=None, zoom=False): if not self.ui.selected: return target = self.ui.selected lat = pi / 2 if target.rotation.is_flipped(): lat = -lat self.go_pole(target, lat, duration, zoom) def go_south(self, duration=None, zoom=False): if not self.ui.selected: return target = self.ui.selected lat = -pi / 2 if target.rotation.is_flipped(): lat = -lat self.go_pole(target, lat, duration, zoom) def go_meridian(self, duration=None, zoom=False): if not self.ui.selected: return target = self.ui.selected if zoom: distance = settings.default_distance else: distance_unit = target.get_apparent_radius() if distance_unit == 0.0: distance_unit = target.get_extend() distance = target.distance_to_obs / distance_unit self.go_to_object_long_lat(0, 0, duration, distance) def align_on_ecliptic(self, duration=None): if duration is None: duration = settings.fast_move ecliptic_normal = self.ship._frame_rotation.conjugate().xform(J2000EclipticReferenceFrame.orientation.xform(LVector3d.up())) angle = acos(ecliptic_normal.dot(LVector3d.right())) direction = ecliptic_normal.cross(LVector3d.right()).dot(LVector3d.forward()) if direction < 0: angle = 2 * pi - angle rot=LQuaterniond() rot.setFromAxisAngleRad(pi / 2 - angle, LVector3d.forward()) self.ship.step_turn(rot, absolute=False) #self.move_and_rotate_to(position, orientation, duration=duration) def align_on_equatorial(self, duration=None): if duration is None: duration = settings.fast_move ecliptic_normal = self.ship._frame_rotation.conjugate().xform(J2000EquatorialReferenceFrame.orientation.xform(LVector3d.up())) angle = acos(ecliptic_normal.dot(LVector3d.right())) direction = ecliptic_normal.cross(LVector3d.right()).dot(LVector3d.forward()) if direction < 0: angle = 2 * pi - angle rot=LQuaterniond() rot.setFromAxisAngleRad(pi / 2 - angle, LVector3d.forward()) self.ship.step_turn(rot, absolute=False) def do_change_distance(self, delta, rate): target = self.ui.selected center = target.get_rel_position_to(self.ship._global_position) min_distance = target.get_apparent_radius() natural_distance = 4.0 * min_distance relative_pos = self.ship.get_pos() - center if target.distance_to_obs < min_distance: min_distance = target.distance_to_obs * 0.5 if target.distance_to_obs >= min_distance and natural_distance != 0: r = (target.distance_to_obs - min_distance) / natural_distance new_distance = min_distance + natural_distance * exp(log(r) + rate * delta) new_pos = relative_pos * (new_distance / target.distance_to_obs) self.ship.set_pos(center + new_pos) def change_distance(self, rate, duration=None): print("Change distance") if duration is None: duration = settings.fast_move self.update_func(self.do_change_distance, duration, [rate]) def do_orbit(self, delta, axis, rate): target = self.ui.selected center = target.get_rel_position_to(self.ship._global_position) center = self.ship.get_rel_position_of(center) relative_pos = self.ship.get_frame_pos() - center rot=LQuaterniond() rot.setFromAxisAngleRad(rate * delta, axis) rot2 = self.ship._frame_rotation.conjugate() * rot * self.ship._frame_rotation rot2.normalize() new_pos = rot2.conjugate().xform(relative_pos) self.ship.set_frame_pos(new_pos + center) self.ship.turn(self.ship._frame_rotation * rot2, absolute=False) def orbit(self, axis, rate, duration=None): print("Orbit") if duration is None: duration = settings.slow_move self.update_func(self.do_orbit, duration, [axis, rate]) def do_rotate(self, delta, axis, rate): rot=LQuaterniond() rot.setFromAxisAngleRad(rate * delta, axis) self.ship.step_turn(rot, absolute=False) def rotate(self, axis, rate, duration=None): print("Rotate") if duration is None: duration = settings.slow_move self.update_func(self.do_rotate, duration, [axis, rate])
def zoomOut(self): i = LerpFunc(self.setZoom, fromData = self.ZOOMLEVEL, toData = self.ZOOMLEVEL*1.3, duration = 1.0,blendType = "easeInOut") i.start()
def rotateCube(self,direction): """ rotates the cube according to the direction passed as first argument. accepted values are "up" "down" "left" "right" """ #first check if we are allowed to move the block at all.. if self.isAnimated() : print "canceling rotation of cube" return #cleaning up from last rotation (we cant clean those up at the end of this function cause the interval needs the dummynode for rotation) self.cube.wrtReparentTo(render) try: dummy.remove_node() except: pass self.setAnimated(True) duration = 0.2 x1,y1,x2,y2 = self.getCubeTiles() self.level.animateTile(x1,y1) self.level.animateTile(x2,y2) dummy = render.attachNewNode("dummy") dummy.reparentTo(self.cube) dummy.setZ(render,0) dummy.wrtReparentTo(render) dummy.setHpr(0,0,0) dest_hpr = Vec3(0) if self.cube.getZ(render) > .7: #case1 : cube is standing upright #ok... since we rotate relative there are rounding errors... since there !might! be some uebernoob playing the game #needing one gazillion rotations to reach the goal it might happen those rounding errors actually get visible #so let him enjoy and reset the cube every-time it's standing straight-up. self.cube.setZ(render,1) #how comes this is one?.. well.. i know.. because of my learnings.. self.cube.setX(render, round(self.cube.getX(render),0) ) self.cube.setY(render, round(self.cube.getY(render),0) ) self.cube.setH(render, round(self.cube.getH(render),0) ) self.cube.setP(render, round(self.cube.getP(render),0) ) self.cube.setR(render, round(self.cube.getR(render),0) ) if direction == "right": dummy.setY(dummy,.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, -90, 0) self.setCubeTiles( x1, y1+1 ,x1 , y1+2 ) if direction == "left": dummy.setY(dummy,-.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 90, 0) self.setCubeTiles( x1, y1-2 ,x1 , y1-1 ) if direction == "up": dummy.setX(dummy,-.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, -90) self.setCubeTiles( x1-2, y1 ,x1-1 , y1 ) if direction == "down": dummy.setX(dummy,.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, 90) self.setCubeTiles( x1+1, y1 ,x1+2 , y1 ) elif x1 == x2 : #if aligned to y-axis if direction == "right": dummy.setY(dummy,1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, -90, 0) self.setCubeTiles( x1, y1+2 ) if direction == "left": dummy.setY(dummy,-1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 90, 0) self.setCubeTiles( x1, y1-1) if direction == "up": dummy.setX(dummy,-.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, -90) self.setCubeTiles( x1-1, y1, x2-1, y2 ) if direction == "down": dummy.setX(dummy,.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, 90) self.setCubeTiles( x1+1, y1, x2+1, y2 ) elif y1==y2 : #if it is alligned to x-axis.. if direction == "right": dummy.setY(dummy,.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, -90, 0) self.setCubeTiles( x1, y1+1, x2, y2+1 ) if direction == "left": dummy.setY(dummy,-.5) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 90, 0) self.setCubeTiles( x1, y1-1, x2, y2-1 ) if direction == "up": dummy.setX(dummy,-1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, -90) self.setCubeTiles( x1-1, y1 ) if direction == "down": dummy.setX(dummy,1) self.cube.wrtReparentTo(dummy) dest_hpr = Vec3(0, 0, 90) self.setCubeTiles( x1+2, y1 ) else: print("Invalid move. Waiting ..") print("Rotating!") anim = self.animate( LerpHprInterval(dummy, duration, dest_hpr,(0,0,0) ) ) #this sorta.. doesnt belong here.. but i dunno where to put it yet. x1,y1,x2,y2 = self.getCubeTiles() # self.level.tintTile(x1,y1) #this is fun to play with if your cube is invisible... # self.level.tintTile(x2,y2) self.level.stopAnimatedTile(x1,y1) #stops the tile-animation for the tiles below the block self.level.stopAnimatedTile(x2,y2) #cheking what consequences your move had... muhahaa... if you get a 1 .. i've got bad news for you checkresult = checkMove(self.level.levelNode,self.getCubeTiles(),self.sounds) if checkresult == 1: self.falls +=1 self.moves +=1 # Force to the corner when the cuboid falls down side_force = 1.7 force = Vec3(0, 0, 0) if direction == "up": force = Vec3(-side_force, 0, 0) elif direction == "down": force = Vec3(side_force, 0, 0) elif direction == "left": force = Vec3(0, -side_force, 0) elif direction == "right": force = Vec3(0, side_force, 0) dummy.set_hpr(render, Vec3(0, 0, 0)) del anim self.setAnimated(True) final_hpr = dest_hpr * 3.0 + Vec3(random(), random(), random()) * 360.0 * 0.0 anim = LerpFunc(self.animateCube, fromData=0, toData=1, duration=1.3, blendType='noBlend', extraArgs=[dummy.get_pos(render), Vec3(0), final_hpr, dummy, force]) taskMgr.doMethodLater( anim.getDuration(), self.resetCube , "resetTask") elif checkresult == 2: #ok.. once reached the goal, move the block down, fading it out. thenload the new level etc. anim.pop() anim.append( Func(lambda: self.level.fadeOutLevel() ) ) Sequence(Wait(0.3), Func(lambda *args: self.cube.hide())).start() taskMgr.doMethodLater( anim.getDuration()+2 , self.levelUp , "lvlup") taskMgr.doMethodLater( anim.getDuration()+2 , lambda *args: self.cube.show(), "show cube") taskMgr.doMethodLater( anim.getDuration()+2 , lambda *args: self.shard_node.node().remove_all_children(), "clear shards") Sequence(Wait(0.2), Func(lambda *args: self.sounds.playSound("finish.wav"))).start() self.moves = 0 self.falls = 0 cube_min, cube_max = Vec3(-0.5, -0.5, -1), Vec3(0.5, 0.5, 1) self.shard_node.set_pos(dummy.get_pos(render) + Vec3(-0.5, 0, 0)) shard_size = (cube_max - cube_min) / 5.0 self.shard_node.hide() Sequence(Wait(0.22), Func(lambda *args: self.shard_node.show())).start() for i in range(5): for j in range(5): for k in range(5): shard = loader.loadModel("models/CubeShard.bam") shard.reparent_to(self.shard_node) shard.set_x(i * shard_size.x + 0.1) shard.set_y(j * shard_size.y + 0.1) shard.set_z(k * shard_size.z + 0.2) shard.set_scale(0.8 + random()) force = Vec3(i-2 - 0.15, j-2 - 0.15, k-2 + 2.6) force.normalize() force *= 12.0 * (1 + random() * 0.5) d_hpr = Vec3(random(), random(), random()) * 360.0 * (3.0 + random()) shard_anim = Sequence( Wait(0.22), LerpFunc(self.animateShard, fromData=0, toData=2, duration=2.0, blendType='noBlend', extraArgs=[shard.get_pos(), d_hpr, shard, force]), LerpHprInterval(shard, 1.0 + random(), d_hpr * 1.6, d_hpr, blendType='noBlend'), ) shard_anim.start() elif checkresult == 0: #how lame... just a ..move.. print "playing sound" self.moves += 1 self.sounds.playSound("stonerotate.wav") print "moves:",self.moves ," falls:",self.falls #last but not least.. we start the animation .. did you know that the pc knows you'r failing before you actually do? .. scary.. anim.start()
class SogalText(NodePath): ''' A text label, contains many TextLines ''' def __init__(self, parent = None, pos = (0,0,0), text = u'', wordwrap = None, maxRows = None, spacing = 0, lineSpacing = 0, minLineHeight = 0.5, font = None, fg = (1,1,1,1), scale = 0.07, shadow = None, shadowOffset = (0.04, 0.04), textScale = None, ): ''' Constructor :param parent: parent NodePath :param text: text :param font: font of the text :param wordwrap: set the width when wraping the word (note that ) :param maxRows: max row of the text :param spacing: spacing of words :param lineSpacing: spacing of lines :param minLineHeight: height of a line when it is empty :param fg: foreground color :param scale: scale of the text :param shadow: shadow color of the text :param shadowOffset: shadow offset of the text ''' self.destroyed = False self.__parent = parent or aspect2d self.__lerpLock = Lock() self.__font = font self.__currentLerpInterval = None self.wordwrap = wordwrap self.lines = [] self.spacing = spacing self.lineSpacing = lineSpacing self.minLineHeight = minLineHeight self.maxRows = maxRows self.recordedText = [] #recorder text sections used in backup NodePath.__init__(self,'') self.setScale(scale) self.setPos(pos) self.currentHeight = 0 self.reparentTo(self.__parent) # @UndefinedVariable self.textMaker = TextNode('textMaker') if font: self.setFont(font, specNode = None) if fg: self.setFg(fg, specNode = None) if shadow: self.setShadow(shadow, shadowOffset, specNode = None) if textScale: self.setTexScale(textScale,specNode = None) self.textMaker.setAlign(TextNode.ALeft) if shadow: pass if text: self.appendText(text) def destroy(self): if self.__currentLerpInterval: self.__currentLerpInterval.pause() self.clear() if not self.destroyed: self.destroyed = True self.textMaker = None self.recordedText = None self.removeNode() def clear(self): if self.__currentLerpInterval: self.__currentLerpInterval.pause() self.currentHeight = 0 for tl in self.lines: tl.removeNode() self.lines = [] self.recordedText = [] def setFg(self, fg, specNode = None): node = specNode or self.textMaker node.setTextColor(fg[0], fg[1], fg[2], fg[3]) def setFont(self,font, specNode = None): node = specNode or self.textMaker node.setFont(font) def setShadow(self, shadow, offset = (0.04, 0.04), specNode = None): node = specNode or self.textMaker if shadow[3] != 0: node.setShadowColor(shadow[0], shadow[1], shadow[2], shadow[3]) node.setShadow(offset) else: node.clearShadow() def setTextScale(self, scale , specNode = None): node = specNode or self.textMaker node.setTextScale(scale) def setMaxRows(self,maxrows): self.maxRows = maxrows def setWordwrap(self,wordwrap): self.wordwrap = wordwrap def setMinLineHeight(self,minLineHeight): self.minLineHeight = minLineHeight def appendText(self, text,speed = 0, fadein = 0, fadeinType = 0, newLine = False, custom = False, font = None, textScale = 1, fg = (1,1,1,1), shadow = None, shadowOffset = (0.04, 0.04), **kwargs): textprops = dict(text = text,newLine = newLine, custom = custom, font = font, textScale = textScale, fg = fg, shadow = shadow, shadowOffset = shadowOffset, **kwargs) self.recordedText.append(textprops) self.appendStoredText(textprops, speed, fadein, fadeinType) def appendStoredText(self,textprops, speed = 0, fadein = 0, fadeinType = 0): #append a text stored with appendText() or by loading self.recordedText text = textprops['text'] newLine = textprops['newLine'] custom = textprops['custom'] if custom: textMaker = TextNode('temptextmaker', self.textMaker) font = textprops['font'] if font: textMaker.setFont(font) textScale = textprops['textScale'] if textScale: textMaker.setTextScale(textScale) fg = textprops['fg'] if fg: self.setFg(fg, textMaker) shadow = textprops['shadow'] shadowOffset = textprops['shadowOffset'] if shadow: self.setShadow(shadow, shadowOffset, textMaker) #prepared to add more props here else: textMaker = self.textMaker if newLine or not self.lines: self.startLine() if not speed: for word in text: self.appendWord(word, tm = textMaker, fadein = fadein, fadeinType = fadeinType) #TYPER EFFECT else: self.__TextLerpInit() self.__currentLerpInterval = LerpFunc(self._appendTextLerpFunc,extraArgs = [text,textMaker,fadein,fadeinType], duration = len(text)/float(speed)) self.__currentLerpInterval.start() def __TextLerpInit(self): if self.__currentLerpInterval: self.__currentLerpInterval.finish() self.__lerpLock.acquire() self.__lastTextLerpValue = 0 self.__lerpLock.release() def _appendTextLerpFunc(self, lerp, text, tm, fadein, fadeinType): '''The function interval method for typer effect''' self.__lerpLock.acquire() tlen = len(text) start = int(math.floor(self.__lastTextLerpValue * tlen)) end = int(math.floor(lerp * tlen)) if end > start: appendingText = text[start:end] for word in appendingText: self.appendWord(word, tm, fadein = fadein, fadeinType = fadeinType) self.__lastTextLerpValue = lerp self.__lerpLock.release() def isWaiting(self): if self.__currentLerpInterval: return self.__currentLerpInterval.isPlaying() return False def quickFinish(self): if self.__currentLerpInterval: return self.__currentLerpInterval.finish() for l in self.lines: l.quickFinish() def appendWord(self,word,tm = None, fadein = 0, fadeinType = 0): if word == '\n': self.startLine() return textMaker = tm or self.textMaker if not self.lines: self.startLine() active_line = self.lines[-1] unicodeText = isinstance(word, types.UnicodeType) if unicodeText: textMaker.setWtext(word) else: textMaker.setText(word) width = textMaker.getWidth() height = textMaker.getHeight() node = textMaker.generate() textpath = NodePath('text_path') textpath.attachNewNode(node) if self.wordwrap: if active_line.getTotalWidth() + width > self.wordwrap: self.startLine() active_line = self.lines[-1] active_line.append(textpath, width, height,self.spacing, fadein = fadein, fadeinType = fadeinType) active_line.setPos(0,0,-(self.currentHeight + active_line.getLineHeight()) ) def startLine(self): if self.lines: self.currentHeight += self.lines[-1].getLineHeight() + self.lineSpacing line = TextLine(parent = self, height = self.minLineHeight) line.setPos(0,0,-self.currentHeight) self.lines.append(line) def removeNode(self, *args, **kwargs): return NodePath.removeNode(self, *args, **kwargs) def getCurrentText(self): return self.recordedText def getCopiedText(self): return copy.deepcopy(self.recordedText) def loadRecordedText(self,recorded): for section in recorded: self.appendStoredText(section) self.recordedText = copy.copy(recorded) def getNewText(self): if self.recordedText: return self.recordedText[0]['text'] return '' def getEndPos(self): if self.lines: return (self.lines[-1].getEndPos()[0],0 , -(self.currentHeight + self.lines[-1].getLineHeight())) else: return (0,0,0) def hasContent(self): "get if this text label empty" return bool(self.lines)
class Timer: def __init__(self, style): """ Timer class with fun pictures @param style: 0 = SUN, 1 = MOON, 2 = GUN @type style: int """ self.style = style VirtualFileSystem.getGlobalPtr().mount(Filename("mf/timer.mf"), ".", VirtualFileSystem.MFReadOnly) self.egg = loader.loadModel("timer.egg") self.img = None self.interval = None self.types[style](self) def create_sun(self): """ Creates the sun timer """ # load image self.img = OnscreenImage(image=self.egg.find('**/sun'), pos=(1.15, 0, 0.75), color=(255, 255, 0, 1), scale=0.25) # interval self.interval = LerpFunc(self.run_interval, fromData=1, toData=0, duration=TIME) self.interval.start() return def create_moon(self): """ Creates the moon timer """ # load image self.img = OnscreenImage(image=self.egg.find('**/moon-quarter'), pos=(0, 0, 0), color=(1, 1, 1, 1), scale=0.25) # interval self.interval = LerpFunc(self.run_interval, fromData=1, toData=0, duration=TIME) self.interval.start() return def create_gun(self): """ Creates the gun timer """ # load image self.img = OnscreenImage(image=self.egg.find('**/gun-0'), pos=(1.05, 0, 0.75), scale=0.25) # interval self.interval = LerpFunc(self.run_interval, fromData=1, toData=0, duration=TIME) self.interval.start() return def run_interval(self, c): if self.style == SUN: self.img.setColor((1, c, 0, 1)) self.img.setPos(1.15-(c/4), 0, 0.75+(math.sin(math.pi*c)/10)) elif self.style == MOON: self.img.setColor((1, c, c, 1)) self.img.setPos(0.9+(c/4), 0, 0.75+(math.sin(math.pi*c)/10)) elif self.style == GUN: self.img.setHpr(0, 0, 360*(1-c)-60) if c % (1 / 6) < 0.05: if c % (1 / 6) > 0.025: self.img.setColor((1, 40*(c % (1 / 6)), 40*(c % (1 / 6)), 1)) else: self.img.setImage(self.egg.find('**/gun-{}'.format(6 - (round(c / (1 / 6)))))) self.img.setColor((1, 1-40*(c % (1 / 6)), 1-40*(c % (1 / 6)), 1)) else: self.img.setColor((1, 1, 1, 1)) def annihilate(self): self.interval.finish() self.img.destroy() loader.unloadModel(self.egg) VirtualFileSystem.getGlobalPtr().unmount("mf/timer.mf") del self types = { SUN: create_sun, MOON: create_moon, GUN: create_gun }