changeset 477:6b33d80b468b

Projectiles are now part of the scene. Cleaned up the scene update() function. Moved garbage collection to the beginning of the frame. Introduced global object types. Projectiles now only check for collisions in a limited number of scene nodes rather than the entire screen.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Thu, 22 Apr 2010 19:52:34 +0000
parents 78a1eb57c074
children 41f7754f2a4b
files demos/shooter/scripts/common/baseobject.py demos/shooter/scripts/scene.py demos/shooter/scripts/ships/enemies.py demos/shooter/scripts/ships/player.py demos/shooter/scripts/ships/shipbase.py demos/shooter/scripts/weapons.py
diffstat 6 files changed, 96 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/demos/shooter/scripts/common/baseobject.py	Thu Apr 22 01:18:44 2010 +0000
+++ b/demos/shooter/scripts/common/baseobject.py	Thu Apr 22 19:52:34 2010 +0000
@@ -25,6 +25,14 @@
 from scripts.common.helpers import normalize
 from scripts.common.helpers import Rect
 
+
+SHTR_DEFAULT = 0
+SHTR_PLAYER = 1
+SHTR_LASTBOSS = 2
+SHTR_PROJECTILE = 3
+SHTR_ENEMYSHIP = 4
+
+
 class SpaceObject(object):
 	def __init__(self, scene, name, findInstance=True):
 		self._scene = scene
@@ -39,6 +47,7 @@
 		self._running = False
 		self._changedPosition = False
 		self._scenenodeid = -1
+		self._type = SHTR_DEFAULT
 			
 		if findInstance:
 			self._instance = self._layer.getInstance(self._name)
@@ -113,9 +122,6 @@
 		
 	def removeFromScene(self):
 		self._scene.queueObjectForRemoval(self)
-#		if self._instance:
-#			self._layer.deleteInstance(self._instance)
-#			self._instance = None
 
 	def _isRunning(self):
 		return self._running
@@ -167,7 +173,14 @@
 		
 	def _setNodeId(self, id):
 		self._scenenodeid = id
+		
+	def _getType(self):
+		return self._type
+		
+	def _setType(self, objtype):
+		self._type = objtype
 
+	type = property(_getType, _setType)
 	width = property(_getW, _setW)
 	height = property(_getH, _setH)
 	boundingbox = property(_getBoundingBox)	
--- a/demos/shooter/scripts/scene.py	Thu Apr 22 01:18:44 2010 +0000
+++ b/demos/shooter/scripts/scene.py	Thu Apr 22 19:52:34 2010 +0000
@@ -22,7 +22,7 @@
 # ####################################################################
 
 from fife import fife
-from scripts.ships.shipbase import Ship
+from scripts.ships.shipbase import *
 from scripts.ships.player import Player
 from scripts.ships.enemies import *
 from scripts.common.helpers import Rect
@@ -68,8 +68,6 @@
 		self._timemod = 0
 		
 		self._gameover = False
-		
-		self._boss = None
 
 	def destroyScene(self):
 		nodestodelete = list()
@@ -97,8 +95,6 @@
 		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()
@@ -139,7 +135,6 @@
 				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)
 				
@@ -202,30 +197,35 @@
 		loc = obj.instance.getLocation().getExactLayerCoordinates()
 		nodeindex = int(loc.x * self._xscale)
 
-		obj.scenenodeid = nodeindex		
-		self._nodes[nodeindex].spaceobjects.append(obj)
-
-	def addProjectileToScene(self, projectile):
-		self._projectiles.append(projectile)
+		if nodeindex >= 0:
+			obj.scenenodeid = nodeindex
+			self._nodes[nodeindex].spaceobjects.append(obj)
+		else:
+			self.queueObjectForRemoval(obj)
 	
 	def moveObjectInScene(self, obj):
 		loc = obj.instance.getLocation().getExactLayerCoordinates()
 		nodeindex = int(loc.x * self._xscale)
 		
-		if nodeindex != obj.scenenodeid:
-			if obj in self._nodes[obj.scenenodeid].spaceobjects:
-				self._nodes[obj.scenenodeid].spaceobjects.remove(obj)
+		if nodeindex >= 0:
+			if nodeindex != obj.scenenodeid:
+				if obj in self._nodes[obj.scenenodeid].spaceobjects:
+					self._nodes[obj.scenenodeid].spaceobjects.remove(obj)
 
-			obj.scenenodeid = nodeindex
-			self._nodes[nodeindex].spaceobjects.append(obj)
+				self._nodes[nodeindex].spaceobjects.append(obj)
+			
+				obj.scenenodeid = nodeindex
+		else:
+			self.queueObjectForRemoval(obj)
 
 	def removeObjectFromScene(self, obj):
 		for node in self._nodes:
 			if obj in node.spaceobjects:
+				if obj.instance:
+					self._layer.deleteInstance(obj.instance)
+					obj.instance = None
 				node.spaceobjects.remove(obj)
-				self._layer.deleteInstance(obj.instance)
-				obj.instance = None
-				return
+				break
 	
 	def attachCamera(self, cam):
 		self._camera = cam
@@ -244,6 +244,13 @@
 		
 		self._keystate = keystate
 		
+		
+		#some garbage cleanup
+		for obj in self._objectstodelete:
+			self.removeObjectFromScene(obj)
+					
+		self._objectstodelete = list()
+		
 		#update camera location
 		loc = self._camera.getLocation()
 		exactloc = self._camera.getLocation().getExactLayerCoordinates()
@@ -268,17 +275,17 @@
 
 		#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):
+			if obj.type == SHTR_LASTBOSS:
+				if bottomright.x > ((obj.location.getExactLayerCoordinates().x * self._xscale) + 0.5):
 					self.stopCamera()
 
-			if not (obj == self._player and self._gameover):
+			if not (obj.type == SHTR_PLAYER and self._gameover):
 				obj.update()
 			
 			if obj.changedposition:
 				self.moveObjectInScene(obj)
 
-			if obj != self._player:
+			if obj.type != SHTR_PLAYER and obj.type != SHTR_PROJECTILE:
 				if obj.running and obj.boundingbox.intersects(self._player.boundingbox):
 					#player touched an enemy.  Destroy player and 
 					#re-initialize scene
@@ -286,51 +293,34 @@
 						#collision damage of 1
 						self.playerHit(1)
 						obj.applyHit(1)
-						
-#			self._world.renderBoundingBox(obj)
-					
-		
-		
-		#update the list of projectiles
-		projtodelete = list()
-		for p in self._projectiles:
-			p.update()
-			#check to see if the projectile hit any object on the screen
-			for o in screenlist:
-				#cant get hit by your own bullet
-				if p.owner != o:
-					if o.running and p.boundingbox.intersects(o.boundingbox):
-						if o != self._player and p.owner.isplayer:
-							o.applyHit(p.damage)
-							#check if enemy ship was destroyed
-							if not o.running:
-								self._player.applyScore(o.scorevalue)
-							p.destroy()
-						elif o == self._player:
-							#player got hit by a projectile
-							if not self._player.invulnerable:
-								self.playerHit(p.damage)
-								p.destroy()
+
+			elif obj.type == SHTR_PROJECTILE:
+				#could probably just get the nodes in the projectiles scenenode.
+				#use a range to be sure.
+				pcollide = self.getObjectsInRange(obj.scenenodeid - 1, obj.scenenodeid + 1)
+				
+				for o in pcollide:
+					#cant get hit by your own bullet
+					if obj.owner != o and o.type != SHTR_PROJECTILE:
+						if o.running and obj.boundingbox.intersects(o.boundingbox):
+							if o != self._player and obj.owner.type == SHTR_PLAYER:
+								o.applyHit(obj.damage)
+								#check if enemy ship was destroyed
+								if not o.running:
+									self._player.applyScore(o.scorevalue)
+								obj.destroy()
+							elif o == self._player:
+								#player got hit by a projectile
+								if not self._player.invulnerable:
+									self.playerHit(obj.damage)
+									obj.destroy()
 			
-#			self._world.renderBoundingBox(p)
-							
-			
-			#build a list of projectiles to remove (ttl expired)
-			if not p.running:
-				projtodelete.append(p)
+				#queue list of projectiles to remove (ttl expired or has been destroyed)
+				if not obj.running:
+					self.queueObjectForRemoval(obj)
 
-		#remove any expired projectiles 
-		for p in projtodelete:
-			if p in self._projectiles:
-				p.destroy()
-				self._projectiles.remove(p)
-		
-		for obj in self._objectstodelete:
-			self.removeObjectFromScene(obj)
-			self._layer.deleteInstance(obj.instance)
-			obj.instance = None
-			
-		self._objectstodelete = list()
+#			self._world.renderBoundingBox(obj)			
+
 
 				
 	def _getPlayer(self):
--- a/demos/shooter/scripts/ships/enemies.py	Thu Apr 22 01:18:44 2010 +0000
+++ b/demos/shooter/scripts/ships/enemies.py	Thu Apr 22 19:52:34 2010 +0000
@@ -23,6 +23,7 @@
 
 from fife import fife
 from scripts.ships.shipbase import *
+from scripts.common.baseobject import *
 from scripts.common.helpers import Rect
 from scripts.weapons import *
 
@@ -50,6 +51,7 @@
 	def __init__(self, scene, name, instance, findInstance=True):
 		super(Saucer1, self).__init__(scene, name, findInstance)
 		self._instance = instance
+		self._type = SHTR_ENEMYSHIP
 		self._dir = 0
 		self._time = 500
 		self.width = 0.2
@@ -89,6 +91,7 @@
 	def __init__(self, scene, name, instance, findInstance=True):
 		super(Saucer2, self).__init__(scene, name, findInstance)
 		self._instance = instance
+		self._type = SHTR_ENEMYSHIP
 		self._dir = 0
 		self._time = 1000
 		self.width = 0.2
@@ -131,6 +134,7 @@
 	def __init__(self, scene, name, direction, instance, findInstance=True):
 		super(DiagSaucer, self).__init__(scene, name, findInstance)
 		self._instance = instance
+		self._type = SHTR_ENEMYSHIP
 		self.width = 0.2
 		self.height = 0.075
 		
@@ -158,6 +162,7 @@
 	def __init__(self, scene, name, instance, findInstance=True):
 		super(Streaker, self).__init__(scene, name, findInstance)
 		self._instance = instance
+		self._type = SHTR_ENEMYSHIP
 		self.width = 0.2
 		self.height = 0.2		
 		
@@ -192,6 +197,7 @@
 	def __init__(self, scene, name, instance, findInstance=True):
 		super(Boss, self).__init__(scene, name, findInstance)
 		self._instance = instance
+		self._type = SHTR_LASTBOSS
 		self.width = 0.85
 		self.height = 0.25		
 		
--- a/demos/shooter/scripts/ships/player.py	Thu Apr 22 01:18:44 2010 +0000
+++ b/demos/shooter/scripts/ships/player.py	Thu Apr 22 19:52:34 2010 +0000
@@ -22,6 +22,7 @@
 # ####################################################################
 
 from fife import fife
+from scripts.common.baseobject import *
 from scripts.ships.shipbase import *
 from scripts.common.helpers import *
 from scripts.weapons import *
@@ -43,6 +44,8 @@
 	def __init__(self, scene, playerName):
 		super(Player, self).__init__(scene, playerName)
 
+		self._type = SHTR_PLAYER
+
 		self._score = 0
 		self._maxvelocity = 1.5
 		self._acceleration = 1.0
@@ -50,8 +53,6 @@
 		self.width = 0.22
 		self.height = 0.12		
 		
-		self._isplayer = True
-		
 		self._actionlistener = PlayerActionListener(self)
 
 		self._lives = 3		
--- a/demos/shooter/scripts/ships/shipbase.py	Thu Apr 22 01:18:44 2010 +0000
+++ b/demos/shooter/scripts/ships/shipbase.py	Thu Apr 22 19:52:34 2010 +0000
@@ -24,7 +24,7 @@
 from math import sqrt
 
 from fife import fife
-from scripts.common.baseobject import SpaceObject
+from scripts.common.baseobject import *
 from scripts.weapons import Weapon
 
 
@@ -44,7 +44,7 @@
 				self._ship._flashing = False
 				self._ship._flashnumber = 0
 		
-		if action.getId() == 'explode' and not self._ship.isplayer:
+		if action.getId() == 'explode' and not self._ship.type == SHTR_PLAYER:
 			self._ship.removeFromScene()
 
 class Ship(SpaceObject):
@@ -56,8 +56,6 @@
 		self._flashnumber = 0
 		self._flashing = False
 		
-		self._isplayer = False
-		
 		self._hitpoints = 0
 		self._scorevalue = 0
 	
@@ -89,10 +87,6 @@
 			self._instance.act('explode', self._instance.getFacingLocation())
 			super(Ship, self).destroy()
 	
-	def _isPlayer(self):
-		return self._isplayer
-	
-	
 	def _getHitPoints(self):
 		return self._hitpoints
 		
@@ -105,7 +99,6 @@
 	def _setScoreValue(self, value):
 		self._scorevalue = value
 	
-	isplayer = property(_isPlayer)
 	weapon = property(_getWeapon, _setWeapon)
 	hitpoints = property(_getHitPoints, _setHitPoints)
 	scorevalue = property(_getScoreValue, _setScoreValue)
\ No newline at end of file
--- a/demos/shooter/scripts/weapons.py	Thu Apr 22 01:18:44 2010 +0000
+++ b/demos/shooter/scripts/weapons.py	Thu Apr 22 19:52:34 2010 +0000
@@ -22,7 +22,7 @@
 # ####################################################################
 
 from fife import fife
-from scripts.ships.shipbase import SpaceObject
+from scripts.common.baseobject import *
 from scripts.common.helpers import normalize, rotatePoint
 
 class Projectile(SpaceObject):
@@ -31,6 +31,8 @@
 
 		self._obj = self._model.getObject(self._name, "http://www.fifengine.de/xml/tutorial")
 	
+		self._type = SHTR_PROJECTILE
+	
 		self._ttl = timeToLive
 		self._starttime = 0
 		self._totaltime = 0
@@ -58,13 +60,6 @@
 			
 			self._starttime = self._scene.time
 		
-	def destroy(self):
-		if self._instance:
-			self._layer.deleteInstance(self._instance)
-			self._instance = None
-		
-		self._running = False
-		
 	def _getTTL(self):
 		return self._ttl
 	
@@ -132,7 +127,7 @@
 			pjctl = Projectile(self._scene, self._ship, "bullet1", 3000 )
 			pjctl.run(velocity, self._ship.location)
 			self._lastfired = self._scene.time
-			self._scene.addProjectileToScene(pjctl)
+			self._scene.addObjectToScene(pjctl)
 
 class FireBall(Weapon):
 	def __init__(self, scene, ship, firerate):
@@ -150,7 +145,7 @@
 			pjctl = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl.run(velocity, self._ship.location)
 			self._lastfired = self._scene.time
-			self._scene.addProjectileToScene(pjctl)	
+			self._scene.addObjectToScene(pjctl)	
 			
 class FireBallBurst(Weapon):
 	def __init__(self, scene, ship, firerate, burstrate, burstnumber):
@@ -174,7 +169,7 @@
 			if (self._scene.time - self._lastburstfired) > self._burstrate and self._burstcount > 0:
 				pjctl = Projectile(self._scene, self._ship, "fireball", 6000 )
 				pjctl.run(velocity, self._ship.location)
-				self._scene.addProjectileToScene(pjctl)
+				self._scene.addObjectToScene(pjctl)
 				
 				self._lastburstfired = self._scene.time
 				self._burstcount -= 1
@@ -210,31 +205,31 @@
 			
 			pjctl1 = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl1.run(p1, self._ship.location)
-			self._scene.addProjectileToScene(pjctl1)
+			self._scene.addObjectToScene(pjctl1)
 			
 			pjctl2 = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl2.run(p2, self._ship.location)
-			self._scene.addProjectileToScene(pjctl2)
+			self._scene.addObjectToScene(pjctl2)
 	
 			pjctl3 = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl3.run(p3, self._ship.location)
-			self._scene.addProjectileToScene(pjctl3)
+			self._scene.addObjectToScene(pjctl3)
 			
 			pjctl4 = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl4.run(p4, self._ship.location)
-			self._scene.addProjectileToScene(pjctl4)
+			self._scene.addObjectToScene(pjctl4)
 	
 			pjctl5 = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl5.run(p5, self._ship.location)
-			self._scene.addProjectileToScene(pjctl5)
+			self._scene.addObjectToScene(pjctl5)
 			
 			pjctl6 = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl6.run(p6, self._ship.location)
-			self._scene.addProjectileToScene(pjctl6)
+			self._scene.addObjectToScene(pjctl6)
 			
 			pjctl7 = Projectile(self._scene, self._ship, "fireball", 6000 )
 			pjctl7.run(p7, self._ship.location)
-			self._scene.addProjectileToScene(pjctl7)
+			self._scene.addObjectToScene(pjctl7)
 			
 			self._lastfired = self._scene.time