示例#1
0
class PlayHopper(ShowBase):
	def __init__(self):
		ShowBase.__init__(self)
		
		#base.disableAllAudio()

		#----- Setup Bullet World -----
		self.debugNode = BulletDebugNode("Debug")
		self.debugNode.showWireframe(True)
		self.debugNP = self.render.attachNewNode(self.debugNode)

		self.bulletWorld = BulletWorld()
		self.bulletWorld.setGravity(Vec3(0, 0, -9.81))
		self.bulletWorld.setDebugNode(self.debugNP.node())
	
		#----- Setup Buttons ------
		self.buttonMap = []
		
		#----- State Variables -----
		self.isHelping = False
		self.isDebugging = False
		self.isLit = False
		self.isMenuShowing = False
		self.amount = 0
		self.isFatiguing = True
		
		#----- Sounds ------
		self.winSound = base.loader.loadSfx("sounds/jennyWin.m4a")

		#----- Start Screen -----
		self.ui = OnscreenInterface()
		self.ui.createStartScreen()
		self.startBtn = self.ui.startButton()	
		self.startBtn.configure(command = self.levelSelect, extraArgs = [self.setup])
		self.buttonMap.append(self.startBtn)
		
		#----- Level Select -----
		self.level = 0

		#(for developing purposes only), don't forget to uncomment line 152
		#self.setup(2)
	
	def levelSelect(self, command):
		self.destroyButtons()
		self.ui.destroyStartScreen()
		self.ui.createLevelSelectScreen()
	 	self.lev1 = self.ui.levelSelectButton(1, -0.6)
		self.lev1.configure(command = command, extraArgs = [1])
		self.lev1.resetFrameSize()
	 	self.lev2 = self.ui.levelSelectButton(2, 0.55)
		self.lev2.configure(command = command, extraArgs = [2])
		self.lev2.resetFrameSize()

		self.buttonMap.append(self.lev1)
		self.buttonMap.append(self.lev2)

	#----- Hopper Functions -----
	def fatigue(self, task):
		if self.hopper.getHealth() > 0:
			self.hopper.lowerHealth(-8)
		
		if self.hopper.getHealth() == 0:
			self.isFatiguing = False
			return task.done
		else:
			print self.hopper.getHealth()
			self.isFatiguing = True
			return task.again

	def displayWallet(self, amount):
		#---ITF: beautify this ----
		self.wallet.setText("Wallet: "+str(amount))

	#------ Level World Control -----
	def setWorld(self, level):
		if level == 1:
			self.world = Level1World(self.render, self.loader, base, self.bulletWorld, self.hopper)
		else:
			self.world = Level2World(self.render, self.loader, base, self.bulletWorld, self.hopper)

	def changeWorld(self, level):
		self.destroyButtons()
		self.ui.destroyLevelSelectScreen()
		self.world.destroyWorld()
		self.removeTasks()
		self.stopAllSounds()
		self.setWorld(level)	
		self.addMouse()
		self.addTasks()
		if len(self.world.enemies) != 0:
			taskMgr.add(self.world.rayUpdate, "updatePicker")
		self.destroyButtons()
		self.resetHopper()
		self.amount = 0
		self.displayWallet(self.amount)

	def addControls(self):
		#----- Setup/Manipulate Hopper -----
		self.hopper = Hopper(self.render, self.bulletWorld, base)
		self.accept('space', self.hopper.doJump)
		self.accept('w', self.hopper.loopRunning)
		self.accept('w-up', self.hopper.loopWalking)
		self.accept('d', self.hopper.loopWalking)
		self.accept('a', self.hopper.loopWalking)
		self.accept('arrow_up', self.hopper.loopRunning)
		self.accept('arrow_up-up', self.hopper.loopWalking)
		self.accept('arrow_left', self.hopper.loopWalking)
		self.accept('arrow_right', self.hopper.loopWalking)
		self.accept('h', self.toggleHelp)
		self.accept('l', self.toggleLight)
		self.accept('b', self.toggleDebug)
		self.accept('m', self.toggleMenu)
	
	def addMouse(self):
		#----- Mouse Clicking -----
		if len(self.world.enemies) != 0:
			self.accept("mouseRayIntoEnemy", self.world.collideEventIn)
			self.accept("mouseRayOutEnemy", self.world.collideEventOut)
			self.accept("mouse1", self.world.mousePick, ['down'])
			self.accept("mouse1-up", self.world.mousePick, ['up'])
			print "Added mouse ray functions"

	def setup(self, level):
		self.destroyButtons()
		self.ui.destroyLevelSelectScreen()
		#----- Controls -----
		self.addControls()

		#----- Setup World -----
		self.setWorld(level)
		
		self.addMouse()
		#----- Setup Camera -----
		base.camera.reparentTo(self.hopper.hopperModel)
		base.camera.setPos(0, 60, 50)#150.0)
		base.camera.setH(180)
		base.camera.lookAt(self.hopper.hopperModel)

		#----- Tasks -----
		#~ Permanent tasks
		taskMgr.add(self.detectCollisionForGhosts, "detectEndCoinCollision", extraArgs = [self.world.endToken], appendTask = True, uponDeath = self.levelClear)
		for spinner in self.world.spinners:
			taskMgr.add(spinner.spin, "spinnerTask")
		#~ Removable tasks
		if len(self.world.enemies) != 0:
			taskMgr.add(self.world.rayUpdate, "updatePicker")
		taskMgr.add(self.world.update, "update")
		taskMgr.add(self.world.simulateWater, "simulateWater", uponDeath = self.fail)
		taskMgr.doMethodLater(2.5, self.fatigue, "fatigue", uponDeath = self.fail)
		
		for berry in self.world.berries:
			taskMgr.add(berry.spinBerry, "spinBerryTask")
			taskMgr.add(self.detectCollisionForGhosts, "detectBerryCollision", extraArgs = [berry], appendTask = True, uponDeath = berry.collectBerry)
		
		for coin in self.world.coins:
			taskMgr.add(self.detectCollisionForGhosts, "detectCoinCollision", extraArgs = [coin], appendTask = True, uponDeath = coin.collectCoin)
		
		for enemy in self.world.enemies:
			taskMgr.add(self.detectCollision, "detectEnemyCollision", extraArgs = [enemy], appendTask = True)
	
		for platform in self.world.spinningPlatforms:
			taskMgr.add(platform.spinPlatform, "spinPlatformTask")
			

		self.wallet = OnscreenText(text = "Wallet: "+str(self.amount), pos = (-1.1, -0.9), bg = (1, 1, 1, 1), align = TextNode.ACenter, mayChange = True)

	#----- Item Functions -----
	def detectCollisionForGhosts(self, item, task):
		# contactTestPair returns a BulletContactResult object
		contactResult = self.bulletWorld.contactTestPair(self.hopper.getNode(), item.ghostNode) 
		if len(contactResult.getContacts()) > 0:
			print "Hopper is in contact with: ", item.ghostNode.getName()
			if task.name == "detectCoinCollision":
				item.setVolume(1)
				self.amount += item.coinValue
				self.displayWallet(self.amount)
			elif task.name == "detectBerryCollision":
				item.setVolume(1)
				if item.berryValue > 0:
					self.hopper.boostHealth(item.berryValue)
				else:
					self.hopper.lowerHealth(item.berryValue)
			return task.done
		else:
			return task.cont

	def detectCollision(self, cc, task):
		# contactTestPair returns a BulletContactResult object
		if cc.getHealth() != 0:
			contactResult = self.bulletWorld.contactTestPair(self.hopper.getNode(), cc.getNode()) 
			if len(contactResult.getContacts()) > 0:
				if task.name == "detectEnemyCollision":
					cc.setVolume(1)
					self.hopper.lowerHealth(-0.3)
					cc.attack()
				return task.cont
			else:
				return task.cont
		else:
			return task.done
	
	#----- Task Functions -----
	def removeTasks(self):
		taskMgr.remove("update")
		taskMgr.remove("detectCoinCollision")
		taskMgr.remove("detectBerryCollision")
		taskMgr.remove("detectEnemyCollision")
		taskMgr.remove("spinBerryTask")
		taskMgr.remove("spinPlatformTask")
		taskMgr.remove("spinnerTask")
		taskMgr.remove("updatePicker")
		
	def addTasks(self):
		if self.isFatiguing == False: 
			taskMgr.doMethodLater(3, self.fatigue, "fatigue", uponDeath = self.fail)
		
		for coin in self.world.coins:
			print "Inside reset, adding coin task"
			coin.setVolume(0)
			taskMgr.add(self.detectCollisionForGhosts, "detectCoinCollision", extraArgs = [coin], appendTask = True, uponDeath = coin.collectCoin)
			
		for berry in self.world.berries:
			berry.setVolume(0)
			taskMgr.add(berry.spinBerry, "spinBerryTask")
			taskMgr.add(self.detectCollisionForGhosts, "detectBerryCollision", extraArgs = [berry], appendTask = True, uponDeath = berry.collectBerry)
		
		for enemy in self.world.enemies:
			enemy.setVolume(0)
			taskMgr.add(self.detectCollision, "detectEnemyCollision", extraArgs = [enemy], appendTask = True)
	
		for platform in self.world.spinningPlatforms:
			taskMgr.add(platform.spinPlatform, "spinPlatformTask")
	
		taskMgr.add(self.world.update, "update")
		taskMgr.add(self.detectCollisionForGhosts, "detectEndCoinCollision", extraArgs = [self.world.endToken], appendTask = True, uponDeath = self.levelClear)
		taskMgr.add(self.world.simulateWater, "simulateWater", uponDeath = self.fail)
		for spinner in self.world.spinners:
			taskMgr.add(spinner.spin, "spinnerTask")
		if len(self.world.enemies) != 0:
			taskMgr.add(self.world.rayUpdate, "updatePicker")

	#----- Replay Functions -----	
	def reset(self):
		print "Resetting level..."

		for button in self.buttonMap:
			button.destroy()
		
	 	self.resetHopper()
		self.removeTasks()	

		self.stopAllSounds()
		self.world.backgroundMusic.play()
	
		self.world.resetCoins()
		self.world.resetBerries()
		if len(self.world.enemies) != 0:
			self.world.resetEnemies()

		self.addTasks()
		
		self.amount = 0
		self.displayWallet(self.amount)
	
	def levelClear(self, task):
		#Hooray! Level 2 unlocked
		#Menu options:
		# - Main Menu
		# - Quit
		# - Play Again
		# - Next Level
		self.stopAllSounds()
		self.winSound.play()

		self.hopper.freeze = True	
		self.hopper.setHealth(-1)
		self.q = DirectButton(text = ("Quit", "Quit", "Quit", "disabled"), scale = .08, pos = (0, 0, -0.2), command = self.quit)
		self.q.resetFrameSize()
	 	self.b = DirectButton(text = ("Restart Level", "Restart Level", "Restart Level", "disabled"), scale = .08, pos = (0, 0, -0.3) , command = self.reset)
		self.b.resetFrameSize()

		self.buttonMap.append(self.q)
		self.buttonMap.append(self.b)
	
	def resetHopper(self):
		self.hopper.hopperNP.setPos(8, 10, 1)
		self.hopper.hopperNP.setH(90)
		self.hopper.resetHealth()
		self.hopper.loopWalking()
		self.hopper.freeze = False
		
	def fail(self, task):
		self.hopper.freeze = True
		self.hopper.setHealth(-1)
		print "Inside fail; hopper health:"+str(self.hopper.getHealth())
		self.world.backgroundMusic.stop()
		self.world.failSound.play()
		self.c = DirectButton(text = ("Restart Level", "Restart Level", "Restart Level", "disabled"), scale = .08, pos = (0, 0, 0) , command = self.reset)
		self.c.resetFrameSize()

		self.buttonMap.append(self.c)
	
	def quit(self):
		sys.exit()	
	
	def stopAllSounds(self):
		for berry in self.world.berries:
			berry.stopSound()
		for coin in self.world.coins:
			coin.stopSound()
		self.world.failSound.stop()
		self.world.backgroundMusic.stop()
		self.winSound.stop()

	#----- User Input Functions -----
	#ITF: add help menu to ui
	def getHelp(self):
		self.blackFrame = DirectFrame(frameColor=(0, 0, 0, 0.5), frameSize=(-3,3,-3,1),pos=(-1,1,1))
		self.walk = self.addInstructions(0.3, "[W]: Forward")
		self.turnLeft = self.addInstructions(0.2, "[A]: Turn Left")
		self.turnRight = self.addInstructions(0.1, "[D]: Turn Right")
		self.jump = self.addInstructions(0.0, "[Space]: Jump") 
		self.theHelp = self.addInstructions(-0.1, "[H]: Help") 
		self.lighting = self.addInstructions(-0.2, "[L]: Toggle Lighting") 
		self.debugging = self.addInstructions(-0.3, "[B]: Toggle Debugging") 
	
	def destroyHelp(self):
		self.blackFrame.destroy()
		self.walk.destroy()
		self.turnLeft.destroy()
		self.turnRight.destroy()
		self.jump.destroy()
		self.theHelp.destroy()
		self.lighting.destroy()
		self.debugging.destroy()

	def addInstructions(self, pos, msg):
		return OnscreenText(text = msg, style = 1, fg = (1, 1, 1, 1), pos = (0, pos), align= TextNode.ACenter, scale = .1)

	def toggleHelp(self):
		if self.isHelping == False:
			self.getHelp()
			self.isHelping = True
		else:
			self.destroyHelp()
			self.isHelping = False
	
	def toggleDebug(self):
		if self.isDebugging == False:
			self.debugNP.show()
			self.isDebugging = True
		else:
			self.debugNP.hide()
			self.isDebugging = False

	def toggleLight(self):
		if self.isLit == False:
			self.hopper.freeze = True
			self.world.addLight()
			self.isLit = True
			unfreezeSeq = Sequence(Wait(2.0), Func(self.hopper.unfreeze))
			unfreezeSeq.start()
		else:
			self.world.destroyLight()
			self.isLit = False
	
	def toggleMenu(self):
		if self.isMenuShowing == False:
			self.isMenuShowing = True
			self.ui.createMenu()
			self.menuBtn = self.ui.menuButton("Level Select", 0)
			self.menuBtn.configure(command = self.levelSelect, extraArgs = [self.changeWorld])
			self.menuBtn.resetFrameSize()
			self.buttonMap.append(self.menuBtn)
		else:
			self.isMenuShowing = False
			self.ui.destroyMenu()
			self.destroyButtons()

	def destroyButtons(self):
		for button in self.buttonMap:
			button.destroy()