changeset 455:e686b82d93d0

Added the ability to pause the game. Added the main menu.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Wed, 07 Apr 2010 19:37:42 +0000
parents bd7e8f708adf
children 41fd97da94d1
files demos/shooter/gui/mainmenu.xml demos/shooter/run.py demos/shooter/scripts/scene.py demos/shooter/scripts/ships/player.py demos/shooter/scripts/world.py
diffstat 5 files changed, 197 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/shooter/gui/mainmenu.xml	Wed Apr 07 19:37:42 2010 +0000
@@ -0,0 +1,20 @@
+<Container name="Main" position="0,0" size="1024,768" border_size="0" base_color="0,0,0" opaque="1">
+
+<!--
+	<Icon image="gui/backgrounds/800_main_bg.png" position="0,0" size="1024,768" name="main_background_icon"/>
+-->
+
+	<VBox opaque='0' base_color="188, 0, 0" position="412,200" name="main_menu">
+		<HBox>
+			<VBox name="menu">
+				<Button name="continue" text="Continue" min_size="200,0" border_size="0"/>
+				<Button name="new_game" text="New Game" min_size="200,0" border_size="0"/>
+				<Button name="high_scores" text="High Scores" min_size="200,0" border_size="0"/>
+				<Button name="credits" text="Credits" min_size="200,0" border_size="0"/>
+				<Button name="quit" text="Quit" min_size="200,0" border_size="0"/>
+			</VBox>
+
+		</HBox>
+	</VBox>
+
+</Container>
--- a/demos/shooter/run.py	Tue Apr 06 21:25:10 2010 +0000
+++ b/demos/shooter/run.py	Wed Apr 07 19:37:42 2010 +0000
@@ -55,7 +55,8 @@
 		keystr = evt.getKey().getAsString().lower()
 		consumed = False
 		if keyval == fife.Key.ESCAPE:
-			self.quit = True
+			#self.quit = True
+			self.world.showMainMenu()
 			evt.consume()
 
 	def onCommand(self, command):
@@ -63,14 +64,17 @@
 		if self.quit:
 			command.consume()
 
-class Tutorial(ApplicationBase):
+class Shooter(ApplicationBase):
 	def __init__(self):
-		super(Tutorial,self).__init__()
+		super(Shooter,self).__init__()
 		pychan.init(self.engine, debug=False)
-		self.world = world.World(self.engine)
+		
+		self.world = world.World(self, self.engine)
 		self.listener = ApplicationListener(self.engine, self.world)
-		self.world.load("maps/shooter_map1.xml")
 
+	def requestQuit(self):
+		self.breakRequested = True
+		
 	def loadSettings(self):
 		"""
 		Load the settings from a python file and load them into the engine.
@@ -117,7 +121,7 @@
 			self.world.pump()
 
 def main():
-	app = Tutorial()
+	app = Shooter()
 	app.run()
 
 
--- a/demos/shooter/scripts/scene.py	Tue Apr 06 21:25:10 2010 +0000
+++ b/demos/shooter/scripts/scene.py	Wed Apr 07 19:37:42 2010 +0000
@@ -62,6 +62,9 @@
 		
 		self._xscale = self._layer.getCellGrid().getXScale()
 		self._yscale = self._layer.getCellGrid().getYScale()
+		
+		self._paused = False
+		self._timemod = 0
 
 	def initScene(self, mapobj):
 		self._player = Player(self, 'player')
@@ -97,6 +100,14 @@
 		#and finally add the player to the scene
 		self.addObjectToScene(self._player)
 
+	def pause(self, time):
+		self._pausedtime = time
+		self._paused = True
+		
+	def unpause(self, time):
+		self._timemod += time - self._pausedtime
+		self._paused = False
+
 	def getObjectsInNode(self, nodeindex):
 		return self._nodes[nodeindex].instances
 
@@ -139,9 +150,9 @@
 		self._camera.setLocation(self._player.location)
 		
 	def update(self, time, keystate):
-		timedelta = time - self._time
+		timedelta = (time - self._timemod) - self._time
 		self._timedelta = timedelta
-		self._time = time
+		self._time = time - self._timemod
 		
 		self._keystate = keystate
 		
@@ -229,7 +240,10 @@
 	
 	def _getTimeDelta(self):
 		return self._timedelta
-
+		
+	def _getPaused(self):
+		return self._paused
+		
 	player = property(_getPlayer)
 	keystate = property(_getKeyState)
 	camera = property(_getCamera)
@@ -237,4 +251,4 @@
 	model = property(_getModel)
 	time = property(_getTime)
 	timedelta = property(_getTimeDelta)
-		
+	paused = property(_getPaused)	
--- a/demos/shooter/scripts/ships/player.py	Tue Apr 06 21:25:10 2010 +0000
+++ b/demos/shooter/scripts/ships/player.py	Wed Apr 07 19:37:42 2010 +0000
@@ -36,6 +36,8 @@
 		
 		#give player the default weapon (the cannon)
 		self.weapon = Cannon(self._scene, self, 200)
+		
+		self._lives = 3
 	
 	def _getScore(self):
 		return self._score
@@ -44,6 +46,7 @@
 		self._score += sc
 		
 	def destroy(self):
+		self._lives -= 1
 		print "player has been destroyed!"
 	
 	def update(self):
@@ -104,5 +107,8 @@
 
 			self.location = oldpos
 
+	def _getLives(self):
+		return self._lives
 
-	score = property(_getScore)
\ No newline at end of file
+	score = property(_getScore)
+	lives = property(_getLives)
\ No newline at end of file
--- a/demos/shooter/scripts/world.py	Tue Apr 06 21:25:10 2010 +0000
+++ b/demos/shooter/scripts/world.py	Wed Apr 07 19:37:42 2010 +0000
@@ -34,6 +34,55 @@
 from scripts.ships.player import Player
 from scripts.scene import Scene
 
+class MainMenu(object):
+	def __init__(self, world):
+		self._world = world
+		self._widget = pychan.loadXML('gui/mainmenu.xml')
+
+		self._continue = self._widget.findChild(name="continue")
+		self._newgame = self._widget.findChild(name="new_game")
+		self._credits = self._widget.findChild(name="credits")
+		self._highscores = self._widget.findChild(name="high_scores")
+		self._quit = self._widget.findChild(name="quit")
+		
+		self._widget.position = (0,0)
+
+		eventMap = {
+			'continue': self._world.continueGame,
+			'new_game': self._world.newGame,
+			'credits': self._world.showCredits,
+			'high_scores': self._world.showHighScores,
+			'quit': self._world.quit,
+		}
+
+		self._widget.mapEvents(eventMap)		
+		
+		self._continueMinWidth = self._continue.min_width
+		self._continueMinHeight = self._continue.min_height
+		self._continueMaxWidth = self._continue.max_width
+		self._continueMaxHeight = self._continue.max_height	
+
+		
+	def show(self, cont=False):
+		if cont:
+			self._continue.min_width = self._continueMinWidth
+			self._continue.min_height = self._continueMinHeight
+			self._continue.max_width = self._continueMaxWidth
+			self._continue.max_height = self._continueMaxHeight
+			
+		else:
+			self._continue.min_width = 0
+			self._continue.min_height = 0
+			self._continue.max_width = 0
+			self._continue.max_height = 0
+
+		self._continue.adaptLayout()
+		self._widget.show()
+		
+	def hide(self):
+		self._widget.hide()
+		
+
 class World(EventListenerBase):
 	"""
 	The world!
@@ -41,14 +90,13 @@
 	This class handles:
 	  setup of map view (cameras ...)
 	  loading the map
-	  GUI for right clicks
 	  handles mouse/key events which aren't handled by the GUI.
 	   ( by inheriting from EventlistenerBase )
 
-	That's obviously too much, and should get factored out.
 	"""
-	def __init__(self, engine):
+	def __init__(self, app, engine):
 		super(World, self).__init__(engine, regMouse=True, regKeys=True)
+		self._applictaion = app
 		self.engine = engine
 		self.timemanager = engine.getTimeManager()
 		self.eventmanager = engine.getEventManager()
@@ -59,33 +107,78 @@
 		self.pump_ctr = 0
 		self.map = None
 		self.scene = None
+		self._paused = True
+		self._pausedtime = 0
+		self._starttime = 0
+		
+		self._mainmenu = MainMenu(self)
+		self.showMainMenu()
+		
+		self._hudwindow = None
 
+	
+	def showMainMenu(self):
+		if self.scene:
+			self._paused = True
+			cont = True
+		else:
+			cont = False
+			
+		self._mainmenu.show(cont)
+		
+	def showCredits(self):
+		pass
+		
+	def showHighScores(self):
+		pass
+		
+	def quit(self):
+		self.reset()
+		self._applictaion.requestQuit()
+		
 	def reset(self):
-		"""
-		Clear the agent information and reset the moving secondary camera state.
+		#TODO: ensure these get destroyed correctly
+		if self.map:
+			self.model.deleteMap(self.map)
+		self.map = None
+		
+		self.cameras = {}
+		self.scene = None
+
+	def loadLevel(self, filename):
 		"""
-		self.cameras = {}
-
-	def load(self, filename):
-		"""
-		Load a xml map and setup agents and cameras.
+		Load a xml map and setup cameras.
 		"""
 		self.filename = filename
 		self.reset()
-		self.map = loadMapFile(filename, self.engine)
+		self.map = loadMapFile(self.filename, self.engine)
 
 		self.scene = Scene(self.engine, self.map.getLayer('objects'))
 		
-		self.mainwindow = pychan.loadXML('gui/mainwindow.xml')
-		self.fpstext = self.mainwindow.findChild(name="fps")
-		self.velocitytext = self.mainwindow.findChild(name="velocity")
-		self.positiontext = self.mainwindow.findChild(name="position")
-		self.scoretext = self.mainwindow.findChild(name="score")
-		self.mainwindow.position = (0,0)
-		self.mainwindow.show()
+		if not self._hudwindow:
+			self._hudwindow = pychan.loadXML('gui/mainwindow.xml')
+			self.fpstext = self._hudwindow.findChild(name="fps")
+			self.velocitytext = self._hudwindow.findChild(name="velocity")
+			self.positiontext = self._hudwindow.findChild(name="position")
+			self.scoretext = self._hudwindow.findChild(name="score")
+			self._hudwindow.position = (0,0)
 		
 		self.scene.initScene(self.map)
 		self.initCameras()
+
+		self._hudwindow.show()
+		
+		self._starttime = self.timemanager.getTime()
+		
+
+	def newGame(self):
+		self.loadLevel("maps/shooter_map1.xml")
+		self._mainmenu.hide()
+		self._paused = False
+		
+	def continueGame(self):
+		self._mainmenu.hide()
+		self._paused = False
 		
 	def initCameras(self):
 		"""
@@ -113,6 +206,9 @@
 			self.keystate['RIGHT'] = True
 		elif keyval == fife.Key.SPACE:
 			self.keystate['SPACE'] = True
+		elif keyval == fife.Key.P:
+			self._paused = not self._paused
+			self._pausedtime += self.timemanager.getTime()
 		elif keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL):
 			self.keystate['CTRL'] = True
 
@@ -153,29 +249,39 @@
 		Called every frame.
 		"""
 		
+		if not self.scene:
+			return
+		
 		#update the scene
-		self.scene.update(self.timemanager.getTime(), self.keystate)
+		if not self._paused:
+			if self.scene.paused:
+				self.scene.unpause(self.timemanager.getTime() - self._starttime)
+				
+			self.scene.update(self.timemanager.getTime() - self._starttime, self.keystate)
 		
 		
-		#update the HUD
-		avgframe = self.timemanager.getAverageFrameTime()
-		if avgframe > 0:
-			fps = 1 / (avgframe / 1000)
-		else:
-			fps = 0
-		fpstxt = "%3.2f" % fps
-		self.fpstext.text = unicode(fpstxt)
+			#update the HUD
+			avgframe = self.timemanager.getAverageFrameTime()
+			if avgframe > 0:
+				fps = 1 / (avgframe / 1000)
+			else:
+				fps = 0
+			fpstxt = "%3.2f" % fps
+			self.fpstext.text = unicode(fpstxt)
 		
-		player = self.scene.player
-		exactcoords = player.location.getExactLayerCoordinates()
-		pos = "%1.2f" % exactcoords.x + ", %1.2f" % exactcoords.y
-		self.positiontext.text = unicode(pos)
+			player = self.scene.player
+			exactcoords = player.location.getExactLayerCoordinates()
+			pos = "%1.2f" % exactcoords.x + ", %1.2f" % exactcoords.y
+			self.positiontext.text = unicode(pos)
 		
-		vel = "%1.2f" % player.velocity.x + ", %1.2f" % player.velocity.y
-		self.velocitytext.text = unicode(vel)
+			vel = "%1.2f" % player.velocity.x + ", %1.2f" % player.velocity.y
+			self.velocitytext.text = unicode(vel)
 		
-		score = unicode(str(player.score))
-		self.scoretext.text = score
-		
+			score = unicode(str(player.score))
+			self.scoretext.text = score
+			
+		else:
+			if not self.scene.paused:
+				self.scene.pause(self.timemanager.getTime() - self._starttime)
 		
 		self.pump_ctr += 1