changeset 459:302a69c5141d

Player death is now handled a bit nicer. Added invulnerability. Added 3 more enemy types. Fixed a bug in the collision detection routine that caused some objects not to be updated when a collision is detected.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Fri, 09 Apr 2010 17:35:52 +0000
parents e77ebf128a74
children 5e1d6e40d19d
files demos/shooter/maps/shooter_map1.xml demos/shooter/scripts/scene.py demos/shooter/scripts/ships/enemies.py demos/shooter/scripts/ships/player.py demos/shooter/scripts/ships/shipbase.py
diffstat 5 files changed, 149 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/demos/shooter/maps/shooter_map1.xml	Thu Apr 08 21:26:46 2010 +0000
+++ b/demos/shooter/maps/shooter_map1.xml	Fri Apr 09 17:35:52 2010 +0000
@@ -438,12 +438,27 @@
 	<layer y_scale="0.25" y_offset="0.0" pathing="cell_edges_and_diagonals" grid_type="square" id="objects" rotation="0.0" x_scale="0.25" x_offset="0.0" transparency="0">
 		<instances>
 			<i o="ship1" z="0.0" x="7.0" r="0" y="0.0" id="player"></i>
-			<i r="0" id="enemy" x="20.0" o="saucer1" z="0.0" y="-2.0"></i>
-			<i r="0" id="enemy" x="20.0" o="saucer1" z="0.0" y="1.0"></i>
-			<i r="0" id="enemy" x="20.0" o="saucer1" z="0.0" y="4.0"></i>
-			<i r="0" id="enemy" x="20.0" o="saucer1" z="0.0" y="-5.0"></i>
-			<i r="0" id="enemy" x="26.0" o="saucer2" z="0.0" y="-3.0"></i>
-			<i r="0" id="enemy" x="26.0" o="saucer2" z="0.0" y="2.0"></i>
+			<i r="0" id="dodge1" x="20.0" o="saucer1" z="0.0" y="-2.0"></i>
+			<i r="0" id="dodge1" x="20.0" o="saucer1" z="0.0" y="1.0"></i>
+			<i r="0" id="dodge1" x="20.0" o="saucer1" z="0.0" y="4.0"></i>
+			<i r="0" id="dodge1" x="20.0" o="saucer1" z="0.0" y="-5.0"></i>
+			<i r="0" id="dodge2" x="26.0" o="saucer2" z="0.0" y="-3.0"></i>
+			<i r="0" id="dodge2" x="26.0" o="saucer2" z="0.0" y="2.0"></i>
+			
+			<i r="0" id="diag_top_right" x="32.0" o="saucer1" z="0.0" y="-6.0"></i>
+			<i r="0" id="diag_top_right" x="33.0" o="saucer1" z="0.0" y="-7.0"></i>
+			<i r="0" id="diag_top_right" x="34.0" o="saucer1" z="0.0" y="-8.0"></i>
+			<i r="0" id="diag_top_right" x="35.0" o="saucer1" z="0.0" y="-9.0"></i>
+			<i r="0" id="diag_bottom_right" x="32.0" o="saucer1" z="0.0" y="6.0"></i>
+			<i r="0" id="diag_bottom_right" x="33.0" o="saucer1" z="0.0" y="7.0"></i>
+			<i r="0" id="diag_bottom_right" x="34.0" o="saucer1" z="0.0" y="8.0"></i>
+			<i r="0" id="diag_bottom_right" x="35.0" o="saucer1" z="0.0" y="9.0"></i>
+			
+			<i r="0" id="streaker" x="37.0" o="saucer1" z="0.0" y="-2.0"></i>
+			<i r="0" id="streaker" x="37.0" o="saucer1" z="0.0" y="1.0"></i>
+			<i r="0" id="streaker" x="37.0" o="saucer1" z="0.0" y="4.0"></i>
+			<i r="0" id="streaker" x="37.0" o="saucer1" z="0.0" y="-5.0"></i>			
+
 		</instances>
 	</layer>
 	<camera ref_cell_height="256" zoom="1" rotation="0.0" ref_layer_id="background" ref_cell_width="256" id="main" tilt="0.0">
--- a/demos/shooter/scripts/scene.py	Thu Apr 08 21:26:46 2010 +0000
+++ b/demos/shooter/scripts/scene.py	Fri Apr 09 17:35:52 2010 +0000
@@ -69,26 +69,47 @@
 		self._gameover = False
 
 	def initScene(self, mapobj):
+		#initialize our scene array to some arbitrary size
+		for i in range(0,self._maxnodes):
+			self._nodes.append(SceneNode())
+
 		self._player = Player(self, 'player')
 		self._player.width = 0.075
 		self._player.height = 0.075
 		self._player.init()
 		self._player.start()
-				
-		enemies = self._layer.getInstances('enemy')
+
+		enemies = list()
 		
-		#initialize our scene array to some arbitrary size
-		for i in range(0,self._maxnodes):
-			self._nodes.append(SceneNode())
-		
+		temp = self._layer.getInstances('dodge1')
+		enemies.extend(temp)
+
+		temp = self._layer.getInstances('dodge2')
+		enemies.extend(temp)
+
+		temp = self._layer.getInstances("diag_top_right")
+		enemies.extend(temp)
+
+		temp = self._layer.getInstances("diag_bottom_right")
+		enemies.extend(temp)
+
+		temp = self._layer.getInstances("streaker")
+		enemies.extend(temp)
+
 		for instance in enemies:
-			objectName = instance.getObject().getId()
+			objectName = instance.getId()
 			print objectName
 			
-			if objectName == "saucer1":
+			if objectName == "dodge1":
 				enemy = Saucer1(self, 'enemy', False)
-			elif objectName == "saucer2":
+			elif objectName == "dodge2":
 				enemy = Saucer2(self, 'enemy', False)
+			elif objectName == "diag_top_right":
+				enemy = DiagSaucer(self, 'enemy', 0, False)
+			elif objectName == "diag_bottom_right":
+				enemy = DiagSaucer(self, 'enemy', 1, False)
+			elif objectName == "streaker":
+				enemy = Streaker(self, 'enemy', False)
 			else:
 				enemy = Ship(self, 'enemy', False)
 				
@@ -111,26 +132,16 @@
 		self._timemod += time - self._pausedtime
 		self._paused = False
 		
-	def playerDied(self):
+	def playerHit(self):
 		self._player.destroy()
 		if self._player.lives <= -1:
 			self._gameover = True
 			self._world.gameOver()
 			self.removeAllProjectiles()
 			return
-		
-		#TODO: Have to find a better way to do this.  If the player
-		#dies too many times right at the start of the level he will
-		#get pushed past the edge of the map to the left.
-		#IDEA: count down to ready player to start again
-		oldpos = self._player.location
-		pos = oldpos.getExactLayerCoordinates()
-		pos.x -= 5
-		oldpos.setExactLayerCoordinates(pos)
-		self._player.location = oldpos
-		self._camera.setLocation(self._player.location)
-		
-		self.removeAllProjectiles()
+
+		self._player.setInvulnerable(2)
+
 		
 	def removeAllProjectiles(self):
 		projtodelete = list()
@@ -140,9 +151,6 @@
 			
 		for p in projtodelete:
 			self._projectiles.remove(p)		
-		
-	def gameOver(self):
-		self._world.gameOver()
 
 	def getObjectsInNode(self, nodeindex):
 		return self._nodes[nodeindex].instances
@@ -230,8 +238,9 @@
 				if obj.boundingbox.intersects(self._player.boundingbox):
 					#player touched an enemy.  Destroy player and 
 					#re-initialize scene
-					self.playerDied()
-					return
+					if not self._player.invulnerable:
+						self.playerHit()
+					
 		
 		
 		#update the list of projectiles
@@ -252,9 +261,10 @@
 							self.removeObjectFromScene(o)
 						else:
 							#player got hit by a projectile
-							p.destroy()
-							self.playerDied()
-							return
+							if not self._player.invulnerable:
+								p.destroy()
+								self.playerHit()
+							
 			
 			#build a list of projectiles to remove (ttl expired)
 			if not p.running:
--- a/demos/shooter/scripts/ships/enemies.py	Thu Apr 08 21:26:46 2010 +0000
+++ b/demos/shooter/scripts/ships/enemies.py	Fri Apr 09 17:35:52 2010 +0000
@@ -85,4 +85,35 @@
 		
 		self._time += self._scene.timedelta
 		
-		super(Saucer2, self).update()
\ No newline at end of file
+		super(Saucer2, self).update()
+		
+class DiagSaucer(Ship):
+	def __init__(self, scene, name, direction, findInstance=True):
+		super(DiagSaucer, self).__init__(scene, name, findInstance)
+		self.width = 0.2
+		self.height = 0.2
+		
+		if direction == 0:
+			self._ythrust = 0.25
+		else:
+			self._ythrust = -0.25
+		
+		self.weapon = Cannon(self._scene, self, 2000)
+		self.weapon.projectilevelocity = 0.4
+				
+	def update(self):	
+		self.applyThrust(fife.DoublePoint(-0.25,self._ythrust))
+		super(DiagSaucer, self).update()
+		
+class Streaker(Ship):
+	def __init__(self, scene, name, findInstance=True):
+		super(Streaker, self).__init__(scene, name, findInstance)
+		
+		self._maxvelocity = 2.0
+		
+		self.weapon = Cannon(self._scene, self, 2000)
+		self.weapon.projectilevelocity = 1.0
+				
+	def update(self):	
+		self.applyThrust(fife.DoublePoint(-0.40,0))
+		super(Streaker, self).update()
\ No newline at end of file
--- a/demos/shooter/scripts/ships/player.py	Thu Apr 08 21:26:46 2010 +0000
+++ b/demos/shooter/scripts/ships/player.py	Fri Apr 09 17:35:52 2010 +0000
@@ -38,6 +38,7 @@
 		self.weapon = Cannon(self._scene, self, 200)
 		
 		self._lives = 3
+		self._invulnerable = False
 	
 	def init(self):
 		self._lives = 3
@@ -49,15 +50,23 @@
 		self._score += sc
 		
 	def destroy(self):
-		self._lives -= 1
+		if not self._flashing:
+			self._lives -= 1
 		
-		if self._lives < 0:
-			self._lives = -1
+			if self._lives < 0:
+				self._lives = -1
 
-	
+	def setInvulnerable(self, seconds):
+		self.flash(20, 20*seconds)
+		self._invulnerable = True
+
 	def update(self):
 	
 		key = False
+		
+		#player is no longer invulnerable
+		if not self._flashing and self._invulnerable:
+			self._invulnerable = False
 
 		oldpos = self.location
 		
@@ -116,6 +125,10 @@
 
 	def _getLives(self):
 		return self._lives
+		
+	def _getInvulnerable(self):
+		return self._invulnerable
 
 	score = property(_getScore)
-	lives = property(_getLives)
\ No newline at end of file
+	lives = property(_getLives)
+	invulnerable = property(_getInvulnerable)
\ No newline at end of file
--- a/demos/shooter/scripts/ships/shipbase.py	Thu Apr 08 21:26:46 2010 +0000
+++ b/demos/shooter/scripts/ships/shipbase.py	Fri Apr 09 17:35:52 2010 +0000
@@ -33,6 +33,13 @@
 		super(Ship, self).__init__(scene, name, findInstance)
 		
 		self._weapon = None
+		self._flashrate = 0
+		self._flashnumber = 0
+		self._flashing = False
+		self._flashtime = 0
+		
+		#1 = on, 0 = invisible (off)
+		self._flashstate = 1
 	
 	def _setWeapon(self, weapon):
 		self._weapon = weapon
@@ -45,6 +52,36 @@
 			return self._weapon.fire(direction)
 		
 		return None
+		
+	def flash(self, rate, number):
+		"""
+		Flash rate is measured in flashes per second.  A single flash
+		would be an off and on cycle.
+		"""
+		self._flashing = True
+		self._flashrate = rate * 2
+		self._flashnumber = number * 2
+	
+	
+	def update(self):
+		if self._flashing:
+			if self._flashnumber <= 0:
+				self._flashing = False
+				self._instance.get2dGfxVisual().setVisible(True)
+			else:
+				self._flashtime += self._scene.timedelta
+				if self._flashtime >= 1000/self._flashrate:
+					if self._flashstate == 1:
+						self._flashstate = 0
+						self._instance.get2dGfxVisual().setVisible(False)
+					else:
+						self._flashstate = 1
+						self._instance.get2dGfxVisual().setVisible(True)
+						
+					self._flashtime = 0
+					self._flashnumber -= 1
+	
+		super(Ship, self).update()
 	
 	weapon = property(_getWeapon, _setWeapon)
 	
\ No newline at end of file