def updateGUI(self, boundingBox): boundingBox = boundingBox * 2 offsetX = 0.0 offsetZ = 0.0 # would be fine for minimap self.playerobj.setX(self.player.getX() / boundingBox) self.playerobj.setZ(self.player.getY() / boundingBox) # player center if (self.playerobj.getX() > 0.5): offsetX = -(self.playerobj.getX() - 0.5) elif (self.playerobj.getX() < 0.5): offsetX = 0.5 - self.playerobj.getX() # else stays zero if (self.playerobj.getZ() > 0.5): offsetZ = -(self.playerobj.getZ() - 0.5) elif (self.playerobj.getZ() < 0.5): offsetZ = 0.5 - self.playerobj.getZ() self.playerobj.setX(self.playerobj.getX() + offsetX) self.playerobj.setZ(self.playerobj.getZ() + offsetZ) for dot in self.dots: dot.removeNode() # correct way to remove from scene graph del self.dots[:] self.playerobj.setR(-self.player.getH() - 90) newobj = OnscreenImage(image='reddot.png',scale=1.0/60.0, \ parent=self.radar) newobj.setTransparency(TransparencyAttrib.MAlpha) newobj.setX(self.partner.getX() / boundingBox) newobj.setZ(self.partner.getY() / boundingBox) newobj.setX(newobj.getX() + offsetX) newobj.setZ(newobj.getZ() + offsetZ) self.dots.append(newobj) # so can destroy, see call above
class CameraShyFirstPerson(FirstPerson): toonInFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) toonOutOfFocusColor = VBase4(1.0, 1.0, 1.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.cameraFocus = None self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.camFSM = ClassicFSM('CameraFSM', [ State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge) ], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) return def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce('mouse1', self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None return def __mouse1Pressed(self): self.cameraFlashSeq = Sequence( Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore('mouse1') def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, 'rechargeCamera') def __rechargeNextState(self, task): if self.cameraRechargeState == None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove('rechargeCamera') self.cameraRechargeState = None return def __traverse(self, task): if not base.mouseWatcherNode.hasMouse(): return task.cont mpos = base.mouseWatcherNode.getMouse() self.focusRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.focusTrav.traverse(render) if self.focusHandler.getNumEntries() > 0: self.focusHandler.sortEntries() firstObj = self.focusHandler.getEntry(0).getIntoNodePath() avId = firstObj.getParent().getPythonTag('player') avatar = self.mg.cr.doId2do.get(avId) toonInFoc = False if avatar: remoteAvatar = self.mg.getRemoteAvatar(avatar.doId) if remoteAvatar: toonInFoc = True self.__handleToonInFocus(avatar) if not toonInFoc: self.toonToTakePicOf = None self.hasToonInFocus = False if self.cameraFocus.getColorScale() == self.toonInFocusColor: self.cameraFocus.setColorScale(self.toonOutOfFocusColor) return task.cont def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.cameraFocus.setColorScale(self.toonInFocusColor) return def start(self): self.fullyChargedSound = base.loadSfx( 'phase_4/audio/sfx/MG_pairing_match.ogg') self.rechargeSound = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage( image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.cameraFocus = loader.loadModel( 'phase_4/models/minigames/photo_game_viewfinder.bam') self.cameraFocus.reparentTo(base.aspect2d) self.focusTrav = CollisionTraverser('CSFP.focusTrav') ray = CollisionRay() rayNode = CollisionNode('CSFP.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = ray self.focusRayNode = base.camera.attachNewNode(rayNode) self.focusHandler = CollisionHandlerQueue() self.focusTrav.addCollider(self.focusRayNode, self.focusHandler) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) return def reallyStart(self): taskMgr.add(self.__traverse, 'CSFP.__traverse') self.camFSM.request('recharge') base.localAvatar.startTrackAnimToSpeed() FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove('movementTask') taskMgr.remove('CSFP.__traverse') FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.cameraFocus.removeNode() self.cameraFocus = None self.focusHandler = None self.focusRay = None self.focusRayNode.removeNode() self.focusRayNode = None self.focusTrav = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) return def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self) return
class CameraShyFirstPerson(FirstPerson): notify = directNotify.newCategory("CameraShyFirstPerson") defaultColor = VBase4(1.0, 1.0, 1.0, 1.0) toonInFocusColor = VBase4(0.0, 0.7, 0.0, 1.0) toonOutOfFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) redColor = VBase4(0.8, 0.0, 0.0, 1.0) batteryLevelTwoColor = VBase4(0.9, 0.36, 0.0, 1.0) batteryLevelThreeColor = VBase4(0.9, 0.9, 0.0, 1.0) batteryLevelFourColor = VBase4(1.0, 1.0, 0.0, 1.0) batteryLevelFiveColor = VBase4(0.0, 1.0, 0.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.viewfinder = None self.camFSM = ClassicFSM('CameraFSM', [ State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge) ], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce("mouse1", self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None def __mouse1Pressed(self): self.cameraFlashSeq = Sequence( Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() self.viewfinder['image'].setColorScale(self.defaultColor) picData = self.viewfinder.takePictureRaw() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore("mouse1") def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, "rechargeCamera") def __rechargeNextState(self, task): if self.cameraRechargeState is None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) if self.cameraRechargeState <= 1: self.batteryBar.setColorScale(self.redColor) elif self.cameraRechargeState == 2: self.batteryBar.setColorScale(self.batteryLevelTwoColor) elif self.cameraRechargeState == 3: self.batteryBar.setColorScale(self.batteryLevelThreeColor) elif self.cameraRechargeState == 4: self.batteryBar.setColorScale(self.batteryLevelFourColor) else: self.batteryBar.setColorScale(self.batteryLevelFiveColor) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove("rechargeCamera") self.cameraRechargeState = None def __traverse(self, task): if not base.mouseWatcherNode.hasMouse(): return task.cont toonInFoc = False avatar = None for av in self.mg.remoteAvatars: if av.avId != base.localAvatar.doId: if self.viewfinder.isInView(av): self.notify.info("{0} is in our view finder".format( av.avId)) avatar = self.mg.cr.doId2do.get(av.avId) break if avatar: remoteAvatar = self.mg.getRemoteAvatar(avatar.doId) if remoteAvatar: toonInFoc = True self.notify.info("We've got an avatar in focus ({0})".format( avatar.doId)) self.__handleToonInFocus(avatar) if not toonInFoc: self.toonToTakePicOf = None self.hasToonInFocus = False self.notify.info("No avatar in focus") if self.viewfinder['image'].getColorScale( ) == self.toonInFocusColor: self.viewfinder['image'].setColorScale( self.toonOutOfFocusColor) return task.cont def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.viewfinder['image'].setColorScale(self.toonInFocusColor) def start(self): self.fullyChargedSound = base.loadSfx('phase_4/audio/sfx/ring_get.ogg') self.rechargeSound = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage( image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBg.setColorScale(0, 0, 0, 1) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.viewfinder = Viewfinder(1.0) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) def reallyStart(self): taskMgr.add(self.__traverse, "CSFP.__traverse") self.camFSM.request('recharge') #taskMgr.add(self.movementTask, "movementTask") base.localAvatar.startTrackAnimToSpeed() FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove("movementTask") taskMgr.remove("CSFP.__traverse") FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.viewfinder.cleanup() self.viewfinder = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self)
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) # relevant for DEBUG self.debug = True self.debugLabel = self.makeStatusLabel(0) if (self.debug): self.debugLabel.setText("Debug Mode ON") else: self.debugLabel.setText("Debug Mode OFF") self.statusLabel = self.makeStatusLabel(1) self.collisionLabel = self.makeStatusLabel(2) self.world = self.loader.loadModel("world.bam") self.world.reparentTo(self.render) # relevant for world boundaries self.worldsize = 1024 self.maxspeed = 100.0 self.startPos = Vec3(200, 200, 1) self.startHpr = Vec3(225, 0, 0) self.player = self.loader.loadModel("alliedflanker") self.player.setScale(.2, .2, .2) self.player.reparentTo(self.render) self.resetPlayer() self.startPosPartner = Vec3(200, 200, 1) self.startHprPartner = Vec3(225, 0, 0) self.partner = self.loader.loadModel("alliedflanker") self.partner.setScale(.2, .2, .2) self.partner.reparentTo(self.render) self.resetPartner() # A task to run every frame self.taskMgr.add(self.updateTask, "update") self.keyboardSetup() #performance (to be masked later by fog) and view: self.maxdistance = 400 self.camLens.setFar(self.maxdistance) self.camLens.setFov(60) self.createEnviroment() # relevant for collision and DEBUG self.setupCollisions() self.textCounter = 0 # explosion self.explosionModel = loader.loadModel('explosion') self.explosionModel.reparentTo(self.render) self.explosionModel.setScale(0.0) self.explosionModel.setLightOff() # only one explosion at a time: self.exploding = False self.radar # relevant for DEBUG def makeStatusLabel(self, i): return OnscreenText(style=2, fg=(.5,1,.5,1), pos=(-1.3,0.92-(.08*i)),\ align=TextNode.ALeft, scale = .08, mayChange = 1) # relevant for collision and DEBUG def setupCollisions(self): self.collTrav = CollisionTraverser() self.playerGroundSphere = CollisionSphere(0, 1.5, 56, 1) self.playerGroundCol = CollisionNode('playerSphere') self.playerGroundCol.addSolid(self.playerGroundSphere) # bitmask self.playerGroundCol.setFromCollideMask(BitMask32.bit(0)) self.playerGroundCol.setIntoCollideMask(BitMask32.allOff()) self.world.setCollideMask(BitMask32.bit(0)) # and done self.playerGroundColNp = self.player.attachNewNode( self.playerGroundCol) self.playerGroundHandler = CollisionHandlerQueue() self.collTrav.addCollider(self.playerGroundColNp, self.playerGroundHandler) # DEBUG if (self.debug == True): self.playerGroundColNp.show() self.collTrav.showCollisions(self.render) def keyboardSetup(self): self.keyMap = { "left": 0, "right": 0, "climb": 0, "fall": 0, "accelerate": 0, "decelerate": 0, "fire": 0 } self.accept("escape", sys.exit) self.accept("a", self.setKey, ["accelerate", 1]) self.accept("a-up", self.setKey, ["accelerate", 0]) self.accept("z", self.setKey, ["decelerate", 1]) self.accept("z-up", self.setKey, ["decelerate", 0]) self.accept("arrow_left", self.setKey, ["left", 1]) self.accept("arrow_left-up", self.setKey, ["left", 0]) self.accept("arrow_right", self.setKey, ["right", 1]) self.accept("arrow_right-up", self.setKey, ["right", 0]) self.accept("arrow_down", self.setKey, ["climb", 1]) self.accept("arrow_down-up", self.setKey, ["climb", 0]) self.accept("arrow_up", self.setKey, ["fall", 1]) self.accept("arrow_up-up", self.setKey, ["fall", 0]) self.accept("space", self.setKey, ["fire", 1]) self.accept("space-up", self.setKey, ["fire", 0]) base.disableMouse() # or updateCamera will fail def createEnviroment(self): # Fog to hide performance tweak: colour = (0.5, 0.5, 0.5) expfog = Fog("scene-wide-fog") expfog.setColor(*colour) expfog.setExpDensity(0.002) self.render.setFog(expfog) base.setBackgroundColor(*colour) # Our sky skydome = self.loader.loadModel('blue-sky-sphere') skydome.setEffect(CompassEffect.make(self.render)) skydome.setScale(0.08) # bit less than "far" # NOT render - you`ll fly through the sky!: skydome.reparentTo(self.camera) # Our lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.6, .6, .6, 1)) render.setLight(render.attachNewNode(ambientLight)) directionalLight = DirectionalLight("directionalLight") directionalLight.setColor(Vec4(0.8, 0.8, 0.5, 1)) dlnp = self.render.attachNewNode(directionalLight) dlnp.setPos(0, 0, 260) dlnp.lookAt(self.player) self.render.setLight(dlnp) self.render2d = render2d # image scale of 1 fills screen, position defaults to central Scale = 1.0 / 2.5 # decimal point is VITAL self.radar = OnscreenImage(image='radar.png', scale=Scale, \ parent=self.render2d, pos=(-0.95,0,-0.95)) self.radar.setTransparency(TransparencyAttrib.MAlpha) # note the image itself and how it is centered hud = OnscreenImage(image='hud1.png', scale=1, \ parent=self.render2d, pos=(0,0,0)) hud.setTransparency(TransparencyAttrib.MAlpha) self.dots = list() self.playerobj = OnscreenImage(image='playerdot.png', \ scale=1.0/20.0,parent=self.radar) self.playerobj.setTransparency(TransparencyAttrib.MAlpha) def setKey(self, key, value): self.keyMap[key] = value def updateTask(self, task): self.updatePlayer() self.updateCamera() self.updateGUI(self.worldsize) #relevant for collision and DEBUG self.collTrav.traverse(self.render) for i in range(self.playerGroundHandler.getNumEntries()): entry = self.playerGroundHandler.getEntry(i) if (self.debug == True): self.collisionLabel.setText("HIT:" + str(globalClock.getFrameTime())) if (self.exploding == False): self.player.setZ(entry.getSurfacePoint(self.render).getZ() + 5) self.explosionSequence() return Task.cont def updatePlayer(self): if self.exploding == False: #Global Clock #by default, panda runs as fast as it can frame to frame scalefactor = (globalClock.getDt() * self.speed) climbfactor = scalefactor * 0.5 bankfactor = scalefactor speedfactor = scalefactor * 2.9 gravityfactor = ((self.maxspeed - self.speed) / 100.0) * 2.0 #Climb and Fall if (self.keyMap["climb"] != 0 and self.speed > 0.00): #faster you go, quicker you climb self.player.setZ(self.player.getZ() + climbfactor) self.player.setR(self.player.getR() + climbfactor) #quickest return: (:avoids uncoil/unwind) if (self.player.getR() >= 180): self.player.setR(-180) elif (self.keyMap["fall"] != 0 and self.speed > 0.00): self.player.setZ(self.player.getZ() - climbfactor) self.player.setR(self.player.getR() - climbfactor) #quickest return if (self.player.getR() <= -180): self.player.setR( 180 ) #autoreturn - add a bit regardless to make sure it happens elif (self.player.getR() > 0): self.player.setR(self.player.getR() - (climbfactor + 0.1)) if (self.player.getR() < 0): self.player.setR(0) #avoid jitter elif (self.player.getR() < 0): self.player.setR(self.player.getR() + (climbfactor + 0.1)) if (self.player.getR() > 0): self.player.setR(0) #Left and Right if (self.keyMap["left"] != 0 and self.speed > 0.0): self.player.setH(self.player.getH() + bankfactor) self.player.setP(self.player.getP() + bankfactor) #quickest return: if (self.player.getP() >= 180): self.player.setP(-180) elif (self.keyMap["right"] != 0 and self.speed > 0.0): self.player.setH(self.player.getH() - bankfactor) self.player.setP(self.player.getP() - bankfactor) if (self.player.getP() <= -180): self.player.setP(180) #autoreturn elif (self.player.getP() > 0): self.player.setP(self.player.getP() - (bankfactor + 0.1)) if (self.player.getP() < 0): self.player.setP(0) elif (self.player.getP() < 0): self.player.setP(self.player.getP() + (bankfactor + 0.1)) if (self.player.getP() > 0): self.player.setP(0) #throttle control if (self.keyMap["accelerate"] != 0): self.speed += 1 if (self.speed > self.maxspeed): self.speed = self.maxspeed elif (self.keyMap["decelerate"] != 0): self.speed -= 1 if (self.speed < 0.0): self.speed = 0.0 #move forwards - our X/Y is inverted, see the issue self.player.setX( self.player, -speedfactor ) #respect max camera distance else you cannot see the floor post loop the loop! self.applyBoundaries() self.player.setZ(self.player, -gravityfactor) def updateGUI(self, boundingBox): boundingBox = boundingBox * 2 offsetX = 0.0 offsetZ = 0.0 # would be fine for minimap self.playerobj.setX(self.player.getX() / boundingBox) self.playerobj.setZ(self.player.getY() / boundingBox) # player center if (self.playerobj.getX() > 0.5): offsetX = -(self.playerobj.getX() - 0.5) elif (self.playerobj.getX() < 0.5): offsetX = 0.5 - self.playerobj.getX() # else stays zero if (self.playerobj.getZ() > 0.5): offsetZ = -(self.playerobj.getZ() - 0.5) elif (self.playerobj.getZ() < 0.5): offsetZ = 0.5 - self.playerobj.getZ() self.playerobj.setX(self.playerobj.getX() + offsetX) self.playerobj.setZ(self.playerobj.getZ() + offsetZ) for dot in self.dots: dot.removeNode() # correct way to remove from scene graph del self.dots[:] self.playerobj.setR(-self.player.getH() - 90) newobj = OnscreenImage(image='reddot.png',scale=1.0/60.0, \ parent=self.radar) newobj.setTransparency(TransparencyAttrib.MAlpha) newobj.setX(self.partner.getX() / boundingBox) newobj.setZ(self.partner.getY() / boundingBox) newobj.setX(newobj.getX() + offsetX) newobj.setZ(newobj.getZ() + offsetZ) self.dots.append(newobj) # so can destroy, see call above def applyBoundaries(self): if (self.player.getZ() > self.maxdistance): self.player.setZ(self.maxdistance) # should never happen once we add collision, but in case: elif (self.player.getZ() < 0): self.player.setZ(0) # and now the X/Y world boundaries: boundary = False if (self.player.getX() < 0): self.player.setX(0) boundary = True elif (self.player.getX() > self.worldsize): self.player.setX(self.worldsize) boundary = True if (self.player.getY() < 0): self.player.setY(0) boundary = True elif (self.player.getY() > self.worldsize): self.player.setY(self.worldsize) boundary = True # lets not be doing this every frame... if boundary == True and self.textCounter > 30: self.statusLabel.setText("STATUS: MAP END; TURN AROUND") elif self.textCounter > 30: self.statusLabel.setText("STATUS: OK") if self.textCounter > 30: self.textCounter = 0 else: self.textCounter = self.textCounter + 1 def updateCamera(self): #see issue content for how we calculated these: percent = (self.speed / self.maxspeed) self.camera.setPos(self.player, 19.6226 + (10 * percent), 3.8807, 10.2779) self.camera.setHpr(self.player, 94.8996, -12.6549, 1.55508) def resetPlayer(self): self.player.show() self.player.setPos(self.world, self.startPos) self.player.setHpr(self.world, self.startHpr) self.speed = self.maxspeed / 2 def resetPartner(self): self.partner.show() self.partner.setPos(self.world, self.startPosPartner) self.partner.setHpr(self.world, self.startHprPartner) def explosionSequence(self): self.exploding = True self.explosionModel.setPosHpr( Vec3(self.player.getX(), self.player.getY(), self.player.getZ()), Vec3(self.player.getH(), 0, 0)) self.player.hide() taskMgr.add(self.expandExplosion, 'expandExplosion') def expandExplosion(self, Task): # expand the explosion rign each frame until a certain size if self.explosionModel.getScale() < VBase3(60.0, 60.0, 60.0): factor = globalClock.getDt() scale = self.explosionModel.getScale() scale = scale + VBase3(factor * 40, factor * 40, factor * 40) self.explosionModel.setScale(scale) return Task.cont else: self.explosionModel.setScale(0) self.exploding = False self.resetPlayer()
class CameraShyFirstPerson(FirstPerson): toonInFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) toonOutOfFocusColor = VBase4(1.0, 1.0, 1.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.cameraFocus = None self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.camFSM = ClassicFSM('CameraFSM', [State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge)], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) return def movementTask(self, task): if not inputState.isSet('jump') and not base.localAvatar.walkControls.isAirborne and inputState.isSet('forward') or inputState.isSet('reverse') or inputState.isSet('slideLeft') or inputState.isSet('slideRight'): if base.localAvatar.getAnimState() != 'run': base.localAvatar.setAnimState('run') base.localAvatar.playMovementSfx('run') self.mg.sendUpdate('runningAvatar', [base.localAvatar.doId]) elif inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne: if base.localAvatar.getAnimState() != 'jump': base.localAvatar.setAnimState('jump') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('jumpingAvatar', [base.localAvatar.doId]) elif base.localAvatar.getAnimState() != 'neutral': base.localAvatar.setAnimState('neutral') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('standingAvatar', [base.localAvatar.doId]) return task.cont def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce('mouse1', self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None return def __mouse1Pressed(self): self.cameraFlashSeq = Sequence(Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore('mouse1') def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, 'rechargeCamera') def __rechargeNextState(self, task): if self.cameraRechargeState == None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done else: task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove('rechargeCamera') self.cameraRechargeState = None return def __handleRayInto(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.__handleToonInFocus(obj) def __handleRayOut(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.toonToTakePicOf = None self.hasToonInFocus = False if self.cameraFocus.getColorScale() == self.toonInFocusColor: self.cameraFocus.setColorScale(self.toonOutOfFocusColor) return def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.cameraFocus.setColorScale(self.toonInFocusColor) return def start(self): self.fullyChargedSound = base.loadSfx('phase_4/audio/sfx/MG_pairing_match.mp3') self.rechargeSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage(image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.cameraFocus = loader.loadModel('phase_4/models/minigames/photo_game_viewfinder.bam') self.cameraFocus.reparentTo(base.aspect2d) self.focusCollHandler = CollisionHandlerEvent() self.focusCollHandler.setInPattern('%fn-into') self.focusCollHandler.setOutPattern('%fn-out') self.focusCollNode = CollisionNode('mouseRay') self.focusCollNP = base.camera.attachNewNode(self.focusCollNode) self.focusCollNode.setCollideMask(BitMask32(0)) self.focusCollNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = CollisionRay() self.focusRay.setFromLens(base.camNode, 0.0, 0.0) self.focusCollNode.addSolid(self.focusRay) base.cTrav.addCollider(self.focusCollNP, self.focusCollHandler) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) return def reallyStart(self): self.accept('mouseRay-into', self.__handleRayInto) self.accept('mouseRay-out', self.__handleRayOut) self.camFSM.request('recharge') taskMgr.add(self.movementTask, 'movementTask') FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove('movementTask') self.ignore('mouseRay-into') self.ignore('mouseRay-out') FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.cameraFocus.removeNode() self.cameraFocus = None self.focusCollHandler = None self.focusCollNode = None self.focusCollNP.removeNode() self.focusCollNP = None self.focusRay = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) return def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self) return