changeset 498:5ff83f209333

Added positioning to the soundmanager classes Made the player ship explosions positional as usage demonstration
author nihathrael@33b003aa-7bff-0310-803a-e67f0ece8222
date Fri, 14 May 2010 16:23:52 +0000
parents 559a26347730
children 3dff106b945b
files demos/shooter/scripts/ships/shipbase.py engine/python/fife/extensions/soundmanager.py
diffstat 2 files changed, 127 insertions(+), 89 deletions(-) [+]
line wrap: on
line diff
--- a/demos/shooter/scripts/ships/shipbase.py	Wed May 12 22:03:32 2010 +0000
+++ b/demos/shooter/scripts/ships/shipbase.py	Fri May 14 16:23:52 2010 +0000
@@ -33,7 +33,7 @@
 	This class is an action listener that listens for instance actions
 	that are complete.  It is used in this demo to specify what should happen
 	after the object has completed flashing or exploding.
-	
+
 	There should be an instance of this listener for every ship that you want
 	to be removed from the scene after exploding.
 	"""
@@ -41,7 +41,7 @@
 		"""
 		@param ship The ship that this actionlistener belongs to.
 		"""
-		
+
 		fife.InstanceActionListener.__init__(self)
 
 		self._ship = ship
@@ -51,20 +51,20 @@
 		if action.getId() == 'flash':
 			if self._ship._flashing and self._ship._flashnumber > 0:
 				self._ship.instance.act('flash', self._ship.instance.getFacingLocation())
-				self._ship._flashnumber -= 1	
-			else:	
+				self._ship._flashnumber -= 1
+			else:
 				self._ship._flashing = False
 				self._ship._flashnumber = 0
-		
+
 		if action.getId() == 'explode' and not self._ship.type == SHTR_PLAYER:
 			self._ship.removeFromScene()
 
 class Ship(SpaceObject):
 	"""
 	Ship
-	
+
 	This is the base ship object.  The Player and Enemy ship classes inherit
-	this class.  This class extends SpaceObject by allowing Weapons to 
+	this class.  This class extends SpaceObject by allowing Weapons to
 	be attached to the object as well as hit points.
 	"""
 	def __init__(self, scene, name, findInstance=True):
@@ -75,56 +75,56 @@
 		@type name: C{string}
 		@param findInstance: True if the instance you are looking for is already loaded
 		                     False if you want to load the instance yourself
-		                     
+
 		@type findInstance: C{boolean}
-		
+
 		"""
-		
+
 		super(Ship, self).__init__(scene, name, findInstance)
-		
+
 		self._weapon = None
 
 		self._flashnumber = 0
 		self._flashing = False
-		
+
 		self._hitpoints = 0
 		self._scorevalue = 0
-		
+
 		self._hitclip = self._scene.soundmanager.createSoundEmitter("sounds/hit.ogg")
 		self._explodclip = self._scene.soundmanager.createSoundEmitter("sounds/explode.ogg")
-	
+
 	def _setWeapon(self, weapon):
 		self._weapon = weapon
-		
+
 	def _getWeapon(self):
 		return self._weapon
-	
+
 	def flash(self, number):
 		"""
 		Playes the flash animation (or action) the specified number of times
-		
+
 		@param number: An integer specifying the number of times to play the flash animation
 		"""
 		if self._running:
 			self._instance.act('flash', self._instance.getFacingLocation())
 			self._flashnumber = number
-			self._flashing = True	
-	
+			self._flashing = True
+
 	def fire(self, direction):
 		"""
 		Fires the current weapon in the specified direction
-		
+
 		@param direction: A L{fife.DoublePoint()} specifying the direction to fire
 		"""
 		if self._weapon and self._hitpoints > 0:
 			return self._weapon.fire(direction)
-		
+
 		return None
-		
+
 	def applyHit(self, hp):
 		"""
 		Removes the specified number of hit points.  Destroys the ship if necessary.
-		
+
 		@param hp: The number of hit points to remove from the ship.
 		"""
 		self._hitpoints -= hp
@@ -132,28 +132,30 @@
 			self.destroy()
 		else:
 			self._hitclip.play()
-		
+
 	def destroy(self):
 		"""
 		Plays the explode animation (or action)
 		"""
 		if self._running:
 			self._instance.act('explode', self._instance.getFacingLocation())
+			location = self.location.getExactLayerCoordinates()
+			self._explodclip.position = (location.x, location.y)
 			self._explodclip.play()
 			super(Ship, self).destroy()
-	
+
 	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
-	
+
 	weapon = property(_getWeapon, _setWeapon)
 	hitpoints = property(_getHitPoints, _setHitPoints)
 	scorevalue = property(_getScoreValue, _setScoreValue)
--- a/engine/python/fife/extensions/soundmanager.py	Wed May 12 22:03:32 2010 +0000
+++ b/engine/python/fife/extensions/soundmanager.py	Fri May 14 16:23:52 2010 +0000
@@ -28,13 +28,13 @@
 This is a simple implementation of a sound manager that was originaly
 intended for the shooter demo.  It was functional enough that we decided
 to include it in the FIFE extensions.  This is by no means a fully featured
-implementation for several reasons.  It doesnt limit how many sounds can 
-play at once or allow the positioning of sounds.  It does however provide 
+implementation for several reasons.  It doesnt limit how many sounds can
+play at once or allow the positioning of sounds.  It does however provide
 a good starting point for a more advanced version of a sound manager.
 
 Usage::
   soundmanager = SoundManager(my_fife_engine)
-  
+
   emitter = soundmanager.createSoundEmitter("path/filename.ogg")
   emitter.gain = 128
   emitter.play()
@@ -50,10 +50,10 @@
 	"""
 	Wraps the L{fife.SoundEmitter} class.
 
-	This class wraps an instance of a L{fife.SoundEmitter} class along 
+	This class wraps an instance of a L{fife.SoundEmitter} class along
 	with some information about a sound clip (like gain and if its
 	looping).  All instances of SoundEmitter should be created by SoundManager.
-	
+
 	@todo: At some point this class will store positional information
 	and also be responsible for updating the L{fife.SoundEmitter} position.
 	"""
@@ -66,62 +66,65 @@
 		@param soundname: The filename of the sound
 		@type soundname: C{string}
 		@param emitter: A reference to the L{fife.SoundEmitter} associated with this clip
-		@type emitter: L{fife.SoundEmitter} 
-		
+		@type emitter: L{fife.SoundEmitter}
+
 		"""
 		self._soundmanager = soundmanager
 		self._name = soundname
-			
+
 		#The FIFE SoundEmitter associated with this SoundEmitter.
 		#Note that we do NOT own the emitter.
 		self._fifeemitter = emitter
 		self._fifeemitter.thisown = 0
 		self._fifeclipid = clipid
-				
+
 		#0 = mute, 255 = normal volume
 		self._gain = 255.0
 		self._looping = False
-		
+
 		#if you set the callback it will be executed after the sound
 		#has finished playing.
 		self._callback = None
-		
+
 		#length of the sound
 		self._duration = 0
-		
+
 		self._timer = None
-		
+
+		self._position = None
+		self._rolloff = 0
+
 	def play(self):
 		self._soundmanager.playClip(self)
-		
+
 	def stop(self):
 		self._soundmanager.stopClip(self)
-		
+
 	def _getClipID(self):
 		return self._fifeclipid
 
 	def _getGain(self):
 		return self._gain
-		
+
 	def _setGain(self, gain):
 		"""
 		Sets the volume of the L{SoundEmitter}.
-		
+
 		@param gain: Value should be from 0-255.  0 being mute and 255 being the normal
 		volume of the clip.
 		@type gain: C{int}
 		"""
 		self._gain = float(gain)
-		
+
 	def _getLooping(self):
 		return self._looping
-		
+
 	def _setLooping(self, looping):
 		self._looping = looping
-		
+
 	def _getFifeEmitter(self):
 		return self._fifeemitter
-		
+
 	def _setFifeEmitter(self, emitter):
 		self._fifeemitter = emitter
 		if self._fifeemitter:
@@ -134,20 +137,34 @@
 		return self._callback
 
 	def _setCallback(self, cb):
-		self._callback = cb	
-		
+		self._callback = cb
+
 	def _getDuration(self):
 		return self._duration
-	
+
 	def _setDuration(self, millliseconds):
 		self._duration = millliseconds
 
 	def _getTimer(self):
 		return self._timer
-		
+
 	def _setTimer(self, timer):
 		self._timer = timer
 
+	def _setPosition(self, position):
+		self._position = position
+
+	def _getPosition(self):
+		return self._position
+
+	def _setRolloff(self, rolloff):
+		self._rolloff = rolloff
+
+	def _getRolloff(self):
+		return self._rolloff
+
+	rolloff = property(_getRolloff, _setRolloff)
+	position = property(_getPosition, _setPosition)
 	timer = property(_getTimer, _setTimer)
 	clipid = property(_getClipID)
 	gain = property(_getGain, _setGain)
@@ -161,8 +178,8 @@
 	"""
 	A simple sound manager class.
 
-	This class manages and plays all the sounds of the game.  
-	It creates SoundEmitters and ensures that there is only one 
+	This class manages and plays all the sounds of the game.
+	It creates SoundEmitters and ensures that there is only one
 	L{fife.SoundEmitter} per unique sound.
 	"""
 	def __init__(self, engine):
@@ -170,26 +187,32 @@
 		@param engine: A reference to the FIFE engine
 		@type engine: L{fife.Engine}
 		"""
-		
+
 		self._engine = engine
-		
+
 		self._fifesoundmanager = self._engine.getSoundManager()
 		self._fifesoundmanager.init()
-		
+
+		# basic rolloff used for positional sounds
+		self._rolloff = 1.9
+
 		#A dict of fife emitters
 		self._loadedclips = {}
-		
-	def createSoundEmitter(self, filename, forceUnique=False):
+
+	def createSoundEmitter(self, filename, forceUnique=False, position=None):
 		"""
 		Returns a valid SoundEmitter instance.
-		
+
 		@param filename: The relative path and filename of the sound file
 		@type clip: C{string}
 		@param forceUnique: This forces a new L{fife.SoundEmitter} to be created.
-		This is useful if you want more than one instance of the same sound 
+		This is useful if you want more than one instance of the same sound
 		to be played at the same time.
 		@type forceUnique: C{boolean}
-		
+		@param position: The position on the map that the sound emitter
+		is to be created at.
+		@type position: L{tuple}
+
 		@return: Returns a new L{SoundEmitter} instance.
 		@rtype: L{SoundEmitter}
 		"""
@@ -198,7 +221,6 @@
 			fifeemitter = self._fifesoundmanager.createEmitter()
 			fifeemitter.thisown = 0
 			fifeemitter.setSoundClip(clipid)
-			
 			self._loadedclips[filename] = [fifeemitter]
 			clip = SoundEmitter(self, clipid, filename, fifeemitter)
 			clip.duration = fifeemitter.getDuration()
@@ -208,30 +230,33 @@
 				fifeemitter = self._fifesoundmanager.createEmitter()
 				fifeemitter.thisown = 0
 				fifeemitter.setSoundClip(clipid)
-				self._loadedclips[filename].append(fifeemitter)	
+				self._loadedclips[filename].append(fifeemitter)
 			else:
 				fifeemitter = self._loadedclips[filename][0]
-				
+
 			clip = SoundEmitter(self, fifeemitter.getID(), filename, fifeemitter)
 			clip.duration = fifeemitter.getDuration()
-		
+
+		if position is not None:
+			clip.position = position
+			clip.rolloff = self.rolloff
 		return clip
-		
+
 	def playClip(self, clip):
 		"""
-		Plays a sound clip.  
-		
+		Plays a sound clip.
+
 		This function does not use the L{fife.SoundEmitter}
-		"looping" property to loop a sound.  Instead it registers 
+		"looping" property to loop a sound.  Instead it registers
 		a new timer and uses the duration of the clip as the timer length.
-		
-		If the SoundEmitter is invalid (no fifeemitter) then it attempts 
+
+		If the SoundEmitter is invalid (no fifeemitter) then it attempts
 		to load it before playing it.
-		
+
 		@note: This will stop any clips that use the same L{fife.SoundEmitter}.
 		You cannot play the same sound more than once at a time unless you create
 		the SoundEmitter with the forceUnique paramater set to True.
-		
+
 		@param clip: The L{SoundEmitter} to be played
 		@type clip: L{SoundEmitter}
 		"""
@@ -240,7 +265,7 @@
 				if clip.timer:
 					clip.timer.stop()
 					timer = None
-					
+
 				if clip.looping:
 					repeat = 0
 					def real_callback(c, e, g):
@@ -253,7 +278,7 @@
 
 				else:
 					repeat = 1
-					
+
 				clip.timer = fife_timer.Timer(clip.duration, clip.callback, repeat)
 				#clip.timer.start()
 			else:
@@ -266,27 +291,31 @@
 					clip.callback = cbwa(real_callback, clip.fifeemitter, clip.gain)
 					clip.timer = fife_timer.Timer(clip.duration, clip.callback, 0)
 					#clip.timer.start()
-					
-				
+
+
 			clip.fifeemitter.setGain(float(clip.gain)/255.0)
+			if clip.position is not None:
+				# Use 1 as z coordinate, no need to specify it
+				clip.fifeemitter.setPosition(clip.position[0], clip.position[1], 1)
+				clip.fifeemitter.setRolloff(clip.rolloff)
 			clip.fifeemitter.play()
 			if clip.timer:
 				clip.timer.start()
 		else:
 			clip = self.createSoundEmitter(clip.name)
 			self.playClip(clip)
-				
+
 	def stopClip(self, clip):
 		"""
-		Stops playing the sound clip.   Note that this will stop all clips that 
+		Stops playing the sound clip.   Note that this will stop all clips that
 		use the same FIFE emitter.
-		
+
 		@param clip: The SoundEmitter to stop.
 		@type clip: L{SoundEmitter}
 		"""
 		if clip.fifeemitter:
 			clip.fifeemitter.stop()
-			
+
 		if clip.timer:
 			clip.timer.stop()
 			clip.timer = None
@@ -295,20 +324,27 @@
 		for emitterlist in self._loadedclips.values():
 			for emitter in emitterlist:
 				emitter.stop()
-			
+
 	def destroy(self):
 		"""
-		Releases all instances of L{fife.SoundEmitter}.  
-		
+		Releases all instances of L{fife.SoundEmitter}.
+
 		@note: This does not free the resources from the FIFE sound clip pool.
 		"""
 		self.stopAllSounds()
-	
+
 		for emitterlist in self._loadedclips.values():
 			for emitter in emitterlist:
 				self._fifesoundmanager.releaseEmitter(emitter.getID())
 				emitter = None
-		
+
 		self._loadedclips.clear()
+
	def _getRolloff(self):
+		return self._rolloff
+
+	def _setRolloff(self, rolloff):
+		self._rolloff = rolloff
+
+	rolloff = property(_getRolloff, _setRolloff)
 
 __all__ = ['SoundEmitter','SoundManager']