changeset 467:4d0aa75a82f1

Added damage so some enemies take more than one hit to destroy. Added the boss at the end of the level. For some reason the high score dialog box that appears after the level is completed causes a crash. Still looking into this one.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Wed, 14 Apr 2010 16:22:36 +0000
parents 716d44ba42df
children ebbb420a90b9
files demos/shooter/maps/shooter_map1.xml demos/shooter/scripts/scene.py demos/shooter/scripts/ships/enemies.py demos/shooter/scripts/ships/shipbase.py demos/shooter/scripts/weapons.py demos/shooter/scripts/world.py
diffstat 6 files changed, 167 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/demos/shooter/maps/shooter_map1.xml	Tue Apr 13 21:30:51 2010 +0000
+++ b/demos/shooter/maps/shooter_map1.xml	Wed Apr 14 16:22:36 2010 +0000
@@ -563,6 +563,8 @@
 			<i r="0" id="dodge2" x="147.0" o="saucer2" z="0.0" y="1.0"></i>
 			<i r="0" id="streaker" x="147.0" o="saucer2" z="0.0" y="4.0"></i>
 			<i r="0" id="streaker" x="147.0" o="saucer2" z="0.0" y="-5.0"></i>
+			
+			<i r="0" id="boss" x="147.0" o="saucer1" z="0.0" y="0.0"></i>
 
 		</instances>
 	</layer>
--- a/demos/shooter/scripts/scene.py	Tue Apr 13 21:30:51 2010 +0000
+++ b/demos/shooter/scripts/scene.py	Wed Apr 14 16:22:36 2010 +0000
@@ -67,12 +67,37 @@
 		self._timemod = 0
 		
 		self._gameover = False
+		
+		self._boss = None
+
+	def destroyScene(self):
+		nodestodelete = list()
+		objtodelete = list()
+	
+		for node in self._nodes:
+			nodestodelete.append(node)
+			for obj in node.spaceobjects:
+				objtodelete.append(node)
+			
+			for obj in objtodelete:
+				if obj in node.spaceobjects:
+					node.spaceobjects.remove(obj)
+				
+			objtodelete = list()
+					
+		for node in nodestodelete:
+			if node in self._nodes:
+				self._nodes.remove(node)
+			
+		self.removeAllProjectiles()
 
 	def initScene(self, mapobj):
 		#initialize our scene array to some arbitrary size
 		for i in range(0,self._maxnodes):
 			self._nodes.append(SceneNode())
 
+		self._boss = None
+
 		self._player = Player(self, 'player')
 		self._player.init()
 		self._player.start()
@@ -94,6 +119,9 @@
 		temp = self._layer.getInstances("streaker")
 		enemies.extend(temp)
 
+		temp = self._layer.getInstances("boss")
+		enemies.extend(temp)
+
 		for instance in enemies:
 			objectName = instance.getId()
 			print objectName
@@ -108,6 +136,9 @@
 				enemy = DiagSaucer(self, 'enemy', 1, instance, False)
 			elif objectName == "streaker":
 				enemy = Streaker(self, 'enemy', instance, False)
+			elif objectName == "boss":
+				enemy = Boss(self, 'enemy', instance, False)
+				self._boss = enemy
 			else:
 				enemy = Ship(self, 'enemy', instance, False)
 				
@@ -121,6 +152,8 @@
 		#and finally add the player to the scene
 		self.addObjectToScene(self._player)
 		
+		self.startCamera()
+		
 	def pause(self, time):
 		self._pausedtime = time
 		self._paused = True
@@ -138,7 +171,9 @@
 			return
 
 		#self._player.setInvulnerable(2)
-
+		
+	def endLevel(self):
+		self._world.endLevel()
 		
 	def removeAllProjectiles(self):
 		projtodelete = list()
@@ -147,7 +182,8 @@
 			projtodelete.append(p)
 			
 		for p in projtodelete:
-			self._projectiles.remove(p)		
+			if p in self._projectiles:
+				self._projectiles.remove(p)		
 
 	def getObjectsInNode(self, nodeindex):
 		return self._nodes[nodeindex].instances
@@ -189,7 +225,13 @@
 	def attachCamera(self, cam):
 		self._camera = cam
 		self._camera.setLocation(self._player.location)
+	
+	def stopCamera(self):
+		self._cameraspeed = 0
 		
+	def startCamera(self):
+		self._cameraspeed = 0.001
+	
 	def update(self, time, keystate):
 		timedelta = (time - self._timemod) - self._time
 		self._timedelta = timedelta
@@ -201,13 +243,13 @@
 		loc = self._camera.getLocation()
 		exactloc = self._camera.getLocation().getExactLayerCoordinates()
 		#slowly move to the right
-		exactloc.x += timedelta * 0.001
+		exactloc.x += timedelta * self._cameraspeed
 		loc.setExactLayerCoordinates(exactloc)
 		self._camera.setLocation(loc)
 		
 		topleft = self._camera.toMapCoordinates(fife.ScreenPoint(0,0))
 		bottomright = self._camera.toMapCoordinates(fife.ScreenPoint(1024,768))
-
+		
 		#which scene nodes to use to update objects
 		leftnode = int(topleft.x)
 		rightnode = int(bottomright.x) + 1
@@ -218,10 +260,13 @@
 		if rightnode > self._maxnodes:
 			rightnode = self._maxnodes
 		screenlist = self.getObjectsInRange(leftnode, rightnode)
-		
 
 		#update objects on the screen
 		for obj in screenlist:
+			if obj == self._boss:
+				if bottomright.x > ((self._boss.location.getExactLayerCoordinates().x * self._xscale) + 0.5):
+					self.stopCamera()
+
 			if not (obj == self._player and self._gameover):
 				obj.update()
 			
@@ -254,12 +299,11 @@
 				if p.owner != o:
 					if o.running and p.boundingbox.intersects(o.boundingbox):
 						if o != self._player and p.owner.isplayer:
-							self._player.applyScore(100)
+							o.applyHit(p.damage)
+							#check if enemy ship was destroyed
+							if not o.running:
+								self._player.applyScore(o.scorevalue)
 							p.destroy()
-							o.destroy()
-							#TODO:  the destroy functions should spawn an explosion
-							#and also destroy the instance and remove itself from the scene
-							#self.removeObjectFromScene(o)
 						elif o == self._player:
 							#player got hit by a projectile
 							if not self._player.invulnerable:
--- a/demos/shooter/scripts/ships/enemies.py	Tue Apr 13 21:30:51 2010 +0000
+++ b/demos/shooter/scripts/ships/enemies.py	Wed Apr 14 16:22:36 2010 +0000
@@ -35,6 +35,15 @@
 		if action.getId() == 'explode':
 			self._ship.removeFromScene()
 
+class BossActionListener(ShipActionListener):
+	def __init__(self, ship):
+		super(BossActionListener, self).__init__(ship)
+
+	def onInstanceActionFinished(self, instance, action):
+		if action.getId() == 'explode':
+			self._ship.removeFromScene()
+			self._ship.endLevel()
+
 class Saucer1(Ship):
 	def __init__(self, scene, name, instance, findInstance=True):
 		super(Saucer1, self).__init__(scene, name, findInstance)
@@ -49,6 +58,9 @@
 		self.weapon.projectilevelocity = 0.4
 		
 		self._actionlistener = EnemyActionListener(self)
+		
+		self.hitpoints = 1
+		self.scorevalue = 50
 				
 	def update(self):	
 		if self._dir == 1:
@@ -82,6 +94,10 @@
 		self.weapon.projectilevelocity = 0.4
 		
 		self._actionlistener = EnemyActionListener(self)
+		
+		self.hitpoints = 2
+		self.scorevalue = 100
+
 				
 	def update(self):	
 		if self._dir == 1:
@@ -117,6 +133,9 @@
 		self.weapon.projectilevelocity = 0.4
 		
 		self._actionlistener = EnemyActionListener(self)
+		
+		self.hitpoints = 1
+		self.scorevalue = 50
 				
 	def update(self):	
 		self.applyThrust(fife.DoublePoint(-0.25,self._ythrust))
@@ -135,7 +154,33 @@
 		self.weapon.projectilevelocity = 1.0
 		
 		self._actionlistener = EnemyActionListener(self)
-				
+		
+		self.hitpoints = 2
+		self.scorevalue = 150
+		
 	def update(self):	
 		self.applyThrust(fife.DoublePoint(-0.40,0))
-		super(Streaker, self).update()
\ No newline at end of file
+		super(Streaker, self).update()
+		
+class Boss(Ship):
+	def __init__(self, scene, name, instance, findInstance=True):
+		super(Boss, self).__init__(scene, name, findInstance)
+		self._instance = instance
+		self.width = 0.2
+		self.height = 0.2		
+		
+		self._maxvelocity = 2.0
+		
+		self.weapon = Cannon(self._scene, self, 1000)
+		self.weapon.projectilevelocity = 0.5
+		
+		self._actionlistener = BossActionListener(self)
+		
+		self.hitpoints = 20
+		self.scorevalue = 1000
+		
+	def endLevel(self):
+		self._scene.endLevel()
+		
+	def update(self):
+		super(Boss, self).update()
\ No newline at end of file
--- a/demos/shooter/scripts/ships/shipbase.py	Tue Apr 13 21:30:51 2010 +0000
+++ b/demos/shooter/scripts/ships/shipbase.py	Wed Apr 14 16:22:36 2010 +0000
@@ -48,6 +48,9 @@
 		self._flashing = False
 		
 		self._isplayer = False
+		
+		self._hitpoints = 0
+		self._scorevalue = 0
 	
 	def _setWeapon(self, weapon):
 		self._weapon = weapon
@@ -66,6 +69,11 @@
 		
 		return None
 		
+	def applyHit(self, hp):
+		self._hitpoints -= hp
+		if self._hitpoints <= 0:
+			self.destroy()
+		
 	def destroy(self):
 		if self._running:
 			self._instance.act('explode', self._instance.getFacingLocation())
@@ -74,6 +82,20 @@
 	def _isPlayer(self):
 		return self._isplayer
 	
+	
+	def _getHitPoints(self):
+		return self._hitpoints
+		
+	def _setHitPoints(self, hp):
+		self._hitpoints = hp
+		
+	def _getScoreValue(self):
+		return self._scorevalue
+	
+	def _setScoreValue(self, value):
+		self._scorevalue = value
+	
 	isplayer = property(_isPlayer)
 	weapon = property(_getWeapon, _setWeapon)
-	
\ No newline at end of file
+	hitpoints = property(_getHitPoints, _setHitPoints)
+	scorevalue = property(_getScoreValue, _setScoreValue)
\ No newline at end of file
--- a/demos/shooter/scripts/weapons.py	Tue Apr 13 21:30:51 2010 +0000
+++ b/demos/shooter/scripts/weapons.py	Wed Apr 14 16:22:36 2010 +0000
@@ -39,6 +39,8 @@
 		
 		self.width = 0.025
 		self.height = 0.025
+		
+		self._damage = 1
 	
 	def create(self, location):
 		self._instance = self._layer.createInstance(self._obj, location.getExactLayerCoordinates(), "bullet")
@@ -72,9 +74,16 @@
 			super(Projectile, self).update()
 		else:
 			self.destroy()
+			
+	def _getDamage(self):
+		return self._damage
+		
+	def _setDamage(self, dam):
+		self._damage = dam
 		
 	ttl = property(_getTTL)
 	owner = property(_getOwner)
+	damage = property(_getDamage, _setDamage)
 	
 class Weapon(object):
 	def __init__(self, scene, ship, firerate):
--- a/demos/shooter/scripts/world.py	Tue Apr 13 21:30:51 2010 +0000
+++ b/demos/shooter/scripts/world.py	Wed Apr 14 16:22:36 2010 +0000
@@ -79,6 +79,8 @@
 		
 		self._genericrenderer = None
 		
+		self._sceneended = False
+		
 	def showMainMenu(self):
 		if self.scene:
 			self._paused = True
@@ -105,7 +107,12 @@
 		self.map = None
 		
 		self.cameras = {}
-		self.scene = None
+		
+		if self.scene:
+			self.scene.destroyScene()
+			self.scene = None
+			
+		self._sceneended = False
 
 	def loadLevel(self, filename):
 		"""
@@ -193,9 +200,28 @@
 			dlg = pychan.loadXML('gui/highscoredialog.xml')
 			dlg.execute({ 'okay' : "Yay!" })
 			name = dlg.findChild(name='name').text
+			
 			self._highscores.addHighScore(HighScore(name, self.scene.player.score))
 			self._highscores.show()
+	
+	def endLevel(self):
+		#there is only one level so do the high score display
+		self._paused = True
+
+		if self._highscores.isHighScore(self.scene.player.score):
+			score = self.scene.player.score
+			#self.reset()
 			
+			dlg = pychan.loadXML('gui/highscoredialog.xml')
+			dlg.execute({ 'okay' : "Yay!" })
+			name = dlg.findChild(name='name').text
+			
+			#self._highscores.addHighScore(HighScore(name, score))
+			#self._highscores.show()
+			
+		self._sceneended = True
+
+
 
 	def newGame(self):
 		self.loadLevel("maps/shooter_map1.xml")
@@ -275,6 +301,10 @@
 		Called every frame.
 		"""
 	
+		if self._sceneended:
+			self.reset()
+			self.showMainMenu()	
+	
 		if self._genericrenderer:
 			self._genericrenderer.removeAll("quads")
 
@@ -320,4 +350,5 @@
 			if not self.scene.paused:
 				self.scene.pause(self.timemanager.getTime() - self._starttime)
 		
+		
 		self.pump_ctr += 1