changeset 453:cf53848fb187

Scene now gets updated when an object moves from one node to another. Player is now part of the scene. Projectiles can be files by both player and enemies. Some code cleanup.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Tue, 06 Apr 2010 19:12:41 +0000
parents f07d779362da
children bd7e8f708adf
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 demos/shooter/scripts/world.py
diffstat 7 files changed, 179 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/demos/shooter/scripts/common/baseobject.py	Sat Apr 03 19:19:33 2010 +0000
+++ b/demos/shooter/scripts/common/baseobject.py	Tue Apr 06 19:12:41 2010 +0000
@@ -26,9 +26,10 @@
 from scripts.common.helpers import Rect
 
 class SpaceObject(object):
-	def __init__(self, model, name, layer, findInstance=True):
-		self._model = model
-		self._layer = layer
+	def __init__(self, scene, name, findInstance=True):
+		self._scene = scene
+		self._model = self._scene.model
+		self._layer = self._scene.objectlayer
 		self._name = name
 		self._xscale = self._layer.getCellGrid().getXScale()
 		self._yscale = self._layer.getCellGrid().getYScale()		
@@ -37,6 +38,8 @@
 		self._timedelta = 0
 		self._boundingBox = Rect(0,0,0,0)
 		self._running = False
+		self._changedPosition = False
+		self._scenenodeid = -1
 			
 		if findInstance:
 			self._instance = self._layer.getInstance(self._name)
@@ -61,6 +64,12 @@
 			self._boundingBox.y = (exactloc.y - self._boundingBox.h/2) * self._yscale
 				
 			shiploc.setExactLayerCoordinates(exactloc)
+			
+			if shiploc == self.location:
+				self._changePosition = False
+			else:
+				self._changedPosition = True
+			
 			self.location = shiploc
 	
 	def stop(self):
@@ -146,6 +155,15 @@
 	
 	def _setH(self, h):
 		self._boundingBox.h = h
+		
+	def _changedPosition(self):
+		return self._changedPosition
+		
+	def _getNodeId(self):
+		return self._scenenodeid
+		
+	def _setNodeId(self, id):
+		self._scenenodeid = id
 
 	width = property(_getW, _setW)
 	height = property(_getH, _setH)
@@ -154,4 +172,6 @@
 	instance = property(_getInstance, _setInstance)
 	velocity = property(_getVelocity, _setVelocity)
 	maxvelocity = property(_getMaxVelocity, _setMaxVelocity)
-	running = property(_isRunning)
\ No newline at end of file
+	running = property(_isRunning)
+	changedposition = property(_changedPosition)
+	scenenodeid = property(_getNodeId, _setNodeId)
\ No newline at end of file
--- a/demos/shooter/scripts/scene.py	Sat Apr 03 19:19:33 2010 +0000
+++ b/demos/shooter/scripts/scene.py	Tue Apr 06 19:12:41 2010 +0000
@@ -50,7 +50,7 @@
 		self._layer = objectLayer
 		self._nodes = list()
 		
-		self._player = Player(self._model, 'player', self._layer)
+		self._player = Player(self, 'player')
 		self._player.width = 0.075
 		self._player.height = 0.075
 		self._player.start()
@@ -59,12 +59,15 @@
 		self._lasttime = 0
 		
 		self._maxnodes = 128
+		self._xscale = 0
+		
+		self._time = 0
+		self._timedelta = 0
 
 	def initScene(self, mapobj):
-		layer = mapobj.getLayer('objects')
-		xscale = layer.getCellGrid().getXScale()
+		self._xscale = self._layer.getCellGrid().getXScale()
 				
-		enemies = layer.getInstances('enemy')
+		enemies = self._layer.getInstances('enemy')
 		
 		#initialize our scene array to some arbitrary size
 		for i in range(0,self._maxnodes):
@@ -75,18 +78,22 @@
 			print objectName
 			
 			if objectName == "saucer1":
-				enemy = Saucer1(self._model, 'enemy', self._layer, False)
+				enemy = Saucer1(self, 'enemy', False)
 			elif objectName == "saucer2":
-				enemy = Saucer2(self._model, 'enemy', self._layer, False)
+				enemy = Saucer2(self, 'enemy', False)
 			else:
-				enemy = Ship(self._model, 'enemy', self._layer, False)
+				enemy = Ship(self, 'enemy', False)
 				
 			enemy.instance = instance
 			enemy.start()
 
 			loc = instance.getLocation().getExactLayerCoordinates()
-			nodeindex = int(loc.x * xscale)
+			nodeindex = int(loc.x * self._xscale)
+			enemy.scenenodeid = nodeindex
 			self._nodes[nodeindex].spaceobjects.append(enemy)
+			
+		#and finally add the player to the scene
+		self.addObjectToScene(self._player)
 
 	def getObjectsInNode(self, nodeindex):
 		return self._nodes[nodeindex].instances
@@ -98,6 +105,26 @@
 			objects.extend(self._nodes[i].spaceobjects)
 			
 		return objects
+		
+	def addObjectToScene(self, obj):
+		#TODO: search to ensure the object isn't already part of the scene
+		loc = obj.instance.getLocation().getExactLayerCoordinates()
+		nodeindex = int(loc.x * self._xscale)
+		
+		self._nodes[nodeindex].spaceobjects.append(obj)
+		obj.scenenodeid = nodeindex		
+
+	def addProjectileToScene(self, projectile):
+		self._projectiles.append(projectile)
+	
+	def moveObjectInScene(self, obj):
+		loc = obj.instance.getLocation().getExactLayerCoordinates()
+		nodeindex = int(loc.x * self._xscale)
+		
+		if nodeindex != obj.scenenodeid:
+			self._nodes[obj.scenenodeid].spaceobjects.remove(obj)
+			self._nodes[nodeindex].spaceobjects.append(obj)
+			obj.scenenodeid = nodeindex
 	
 	def removeObjectFromScene(self, obj):
 		for node in self._nodes:
@@ -109,16 +136,17 @@
 		self._camera = cam
 		self._camera.setLocation(self._player.location)
 		
-	def _getPlayer(self):
-		return self._player
-
 	def update(self, time, keystate):
-		timedelta = time - self._lasttime
-		self._lasttime = time
+		timedelta = time - self._time
+		self._timedelta = timedelta
+		self._time = time
+		
+		self._keystate = keystate
 		
 		#update camera location
 		loc = self._camera.getLocation()
 		exactloc = self._camera.getLocation().getExactLayerCoordinates()
+		#slowly move to the right
 		exactloc.x += timedelta * 0.001
 		loc.setExactLayerCoordinates(exactloc)
 		self._camera.setLocation(loc)
@@ -137,12 +165,24 @@
 			rightnode = self._maxnodes
 		screenlist = self.getObjectsInRange(leftnode, rightnode)
 		
+
 		#update objects on the screen
 		for obj in screenlist:
 			obj.update(timedelta)
+			if obj.changedposition:
+				self.moveObjectInScene(obj)
 
-		#update the player
-		self._player.update(timedelta, keystate, self._camera)
+				#Testing enemy fire				
+				#prjct = obj.fire(time, fife.DoublePoint(-1,0))
+				#if prjct:
+				#	self._projectiles.append(prjct)
+			
+			if obj != self._player:
+				if obj.boundingbox.intersects(self._player.boundingbox):
+					#player touched an enemy.  Destroy player and 
+					#re-initialize scene
+					self._player.destroy()
+		
 		
 		#update the list of projectiles
 		projtodelete = list()
@@ -150,25 +190,51 @@
 			p.update(timedelta)
 			#check to see if the projectile hit any object on the screen
 			for o in screenlist:
-				if p.boundingbox.intersects(o.boundingbox):
-					self._player.applyScore(100)
-					p.destroy()
-					o.destroy()
-					self.removeObjectFromScene(o)
+				#cant get hit by your own bullet
+				if p.owner != o:
+					if p.boundingbox.intersects(o.boundingbox):
+						self._player.applyScore(100)
+						p.destroy()
+						o.destroy()
+						#temporary...  the destroy functions should spawn an explosion
+						#and also destroy the instance and remove itself from the scene
+						self.removeObjectFromScene(o)
 			
 			#build a list of projectiles to remove (ttl expired)
 			if not p.running:
 				projtodelete.append(p)
 
-		#remove any non running projectiles 
+		#remove any expired projectiles 
 		for p in projtodelete:
 			self._projectiles.remove(p)
+
+				
+	def _getPlayer(self):
+		return self._player
 		
-		#fire the currently selected gun
-		if keystate['SPACE']:
-			prjct = self._player.fire(time)
-			if prjct:
-				self._projectiles.append(prjct)
+	def _getKeyState(self):
+		return self._keystate
+		
+	def _getCamera(self):
+		return self._camera
+		
+	def _getObjectLayer(self):
+		return self._layer
+		
+	def _getModel(self):
+		return self._model
+		
+	def _getTime(self):
+		return self._time
+	
+	def _getTimeDelta(self):
+		return self._timedelta
 
 	player = property(_getPlayer)
+	keystate = property(_getKeyState)
+	camera = property(_getCamera)
+	objectlayer = property(_getObjectLayer)
+	model = property(_getModel)
+	time = property(_getTime)
+	timedelta = property(_getTimeDelta)
 		
--- a/demos/shooter/scripts/ships/enemies.py	Sat Apr 03 19:19:33 2010 +0000
+++ b/demos/shooter/scripts/ships/enemies.py	Tue Apr 06 19:12:41 2010 +0000
@@ -28,13 +28,15 @@
 
 
 class Saucer1(Ship):
-	def __init__(self, model, name, layer, findInstance=True):
-		super(Saucer1, self).__init__(model, name, layer, findInstance)
+	def __init__(self, scene, name, findInstance=True):
+		super(Saucer1, self).__init__(scene, name, findInstance)
 		self._dir = 0
 		self._time = 500
 		self.width = 0.075
 		self.height = 0.075
 		self.velocity.x = -0.5
+		
+		self.weapon = Weapon(self._scene, self, 1000)
 				
 	def update(self, timedelta):	
 		if self._dir == 1:
@@ -55,13 +57,15 @@
 		super(Saucer1, self).update(timedelta)
 		
 class Saucer2(Ship):
-	def __init__(self, model, name, layer, findInstance=True):
-		super(Saucer2, self).__init__(model, name, layer, findInstance)
+	def __init__(self, scene, name, findInstance=True):
+		super(Saucer2, self).__init__(scene, name, findInstance)
 		self._dir = 0
 		self._time = 1000
 		self.width = 0.2
 		self.height = 0.2
 		self.velocity.x = -0.1
+		
+		self.weapon = Weapon(self._scene, self, 2000)
 				
 	def update(self, timedelta):	
 		if self._dir == 1:
--- a/demos/shooter/scripts/ships/player.py	Sat Apr 03 19:19:33 2010 +0000
+++ b/demos/shooter/scripts/ships/player.py	Tue Apr 06 19:12:41 2010 +0000
@@ -27,44 +27,54 @@
 
 
 class Player(Ship):
-	def __init__(self, model, playerName, layer):
-		super(Player, self).__init__(model, playerName, layer)
+	def __init__(self, scene, playerName):
+		super(Player, self).__init__(scene, playerName)
 
 		self._score = 0
+		self._maxvelocity = 1.5
 	
 	def _getScore(self):
 		return self._score
 		
 	def applyScore(self, sc):
 		self._score += sc
+		
+	def destroy(self):
+		print "player has been destroyed!"
 	
-	def update(self, timedelta, keystate, camera):
+	def update(self, timedelta):
 		key = False
-		
+
 		oldpos = self.location
 		
-		if keystate['UP']:
-			self.applyThrust(fife.DoublePoint(0,-0.75), timedelta)
+		if self._scene.keystate['UP']:
+			self.applyThrust(fife.DoublePoint(0,-1.5), timedelta)
 			key = True
-		if keystate['DOWN']:
-			self.applyThrust(fife.DoublePoint(0,0.75), timedelta)
+		if self._scene.keystate['DOWN']:
+			self.applyThrust(fife.DoublePoint(0,1.5), timedelta)
+			key = True
+		if self._scene.keystate['LEFT']:
+			self.applyThrust(fife.DoublePoint(-1.5,0), timedelta)
 			key = True
-		if keystate['LEFT']:
-			self.applyThrust(fife.DoublePoint(-0.75,0), timedelta)
+		if self._scene.keystate['RIGHT']:
+			self.applyThrust(fife.DoublePoint(1.5,0), timedelta)
 			key = True
-		if keystate['RIGHT']:
-			self.applyThrust(fife.DoublePoint(0.75,0), timedelta)
-			key = True
+		
+		#fire the currently selected gun
+		if self._scene.keystate['SPACE']:
+			prjct = self.fire(self._scene.time, fife.DoublePoint(1,0))
+			if prjct:
+				self._scene.addProjectileToScene(prjct)
 			
 		if not key and self._velocity.length() > 0:
-			self.applyBrake(0.75, timedelta)
+			self.applyBrake(1.5, timedelta)
 		
 		super(Player, self).update(timedelta)
 		
 		#set up the players camera bounds
 		#TODO: grab screen resolution from somewhere
-		topleft = camera.toMapCoordinates(fife.ScreenPoint(0,0))
-		bottomright = camera.toMapCoordinates(fife.ScreenPoint(1024,768))
+		topleft = self._scene.camera.toMapCoordinates(fife.ScreenPoint(0,0))
+		bottomright = self._scene.camera.toMapCoordinates(fife.ScreenPoint(1024,768))
 
 		camrect = Rect(topleft.x, topleft.y, bottomright.x - topleft.x, bottomright.y - topleft.y)
 	
--- a/demos/shooter/scripts/ships/shipbase.py	Sat Apr 03 19:19:33 2010 +0000
+++ b/demos/shooter/scripts/ships/shipbase.py	Tue Apr 06 19:12:41 2010 +0000
@@ -29,8 +29,8 @@
 
 
 class Ship(SpaceObject):
-	def __init__(self, model, name, layer, findInstance=True):
-		super(Ship, self).__init__(model, name, layer, findInstance)
+	def __init__(self, scene, name, findInstance=True):
+		super(Ship, self).__init__(scene, name, findInstance)
 
 		self._timedelta = 0
 		self._weapon = None
@@ -41,9 +41,9 @@
 	def _getWeapon(self, weapon):
 		return self._weapon
 		
-	def fire(self, curtime):
+	def fire(self, curtime, direction):
 		if self._weapon:
-			return self._weapon.fire(curtime)
+			return self._weapon.fire(curtime, direction)
 		
 		return None
 	
--- a/demos/shooter/scripts/weapons.py	Sat Apr 03 19:19:33 2010 +0000
+++ b/demos/shooter/scripts/weapons.py	Tue Apr 06 19:12:41 2010 +0000
@@ -23,18 +23,22 @@
 
 from fife import fife
 from scripts.ships.shipbase import SpaceObject
+from scripts.common.helpers import normalize
 
 class Projectile(SpaceObject):
-	def __init__(self, model, projectileName, layer, timeToLive):
-		super(Projectile, self).__init__(model, projectileName, layer, False)
-		self._name = projectileName
-		self._layer = layer
+	def __init__(self, scene, owner, projectileName, timeToLive):
+		super(Projectile, self).__init__(scene, projectileName, False)
 
 		self._obj = self._model.getObject(self._name, "http://www.fifengine.de/xml/tutorial")
 	
 		self._ttl = timeToLive
 		self._starttime = 0
 		self._totaltime = 0
+		
+		self._owner = owner
+		
+		self.width = 0.025
+		self.height = 0.025
 	
 	def create(self, location):
 		self._instance = self._layer.createInstance(self._obj, location.getExactLayerCoordinates(), "bullet")
@@ -58,6 +62,9 @@
 		
 	def _getTTL(self):
 		return self._ttl
+	
+	def _getOwner(self):
+		return self._owner
 
 	def update(self, timedelta):
 		self._totaltime += timedelta
@@ -67,22 +74,26 @@
 			self.destroy()
 		
 	ttl = property(_getTTL)
+	owner = property(_getOwner)
 	
 class Weapon(object):
-	def __init__(self, model, layer, ship, firerate):
-		self._model = model
-		self._layer = layer
+	def __init__(self, scene, ship, firerate):
+		self._scene = scene
+		self._model = self._scene.model
+		self._layer = self._scene.objectlayer
 		self._ship = ship
 		self._firerate = firerate
 		self._lastfired = 0
-		self._projectileVelocity = fife.DoublePoint(0.75,0)
+		self._projectileVelocity = 0.75
 		
-	def fire(self, curtime):
+	def fire(self, curtime, direction):
+		velocity = normalize(direction)
+		velocity.x = velocity.x * self._projectileVelocity
+		velocity.y = velocity.y * self._projectileVelocity
+	
 		if (curtime - self._lastfired) > self._firerate:
-			pjctl = Projectile(self._model, "bullet1", self._layer, 2000 )
-			pjctl.width = 0.025
-			pjctl.height = 0.025
-			pjctl.run(fife.DoublePoint(self._projectileVelocity.x,self._projectileVelocity.y), self._ship.location, curtime)
+			pjctl = Projectile(self._scene, self._ship, "bullet1", 2000 )
+			pjctl.run(velocity, self._ship.location, curtime)
 			self._lastfired = curtime
 			return pjctl
 		
--- a/demos/shooter/scripts/world.py	Sat Apr 03 19:19:33 2010 +0000
+++ b/demos/shooter/scripts/world.py	Tue Apr 06 19:12:41 2010 +0000
@@ -88,7 +88,7 @@
 		self.mainwindow.show()
 		
 		#give player the default weapon
-		self.scene.player.weapon = Weapon(self.model, self.map.getLayer('objects'), self.scene.player, 200)
+		self.scene.player.weapon = Weapon(self.scene, self.scene.player, 200)
 		self.scene.initScene(self.map)
 		
 	def initCameras(self):