# HG changeset patch # User prock@33b003aa-7bff-0310-803a-e67f0ece8222 # Date 1273266447 0 # Node ID 16ceb32283244f17f2c7319fb77454268eb3beb2 # Parent c4168eb47a442acf33c2c9fa4d653a2f7c6d69a5 Moved the SoundManager and the 2D math function (helpers) from the shooter demo to the fife extensions. Fixed fife_timer as it didn't work in the first place. Modified the SoundManager to use the now working fife_timer and removed the Timer class from the shooter demo entirely diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/common/baseobject.py --- a/demos/shooter/scripts/common/baseobject.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/common/baseobject.py Fri May 07 21:07:27 2010 +0000 @@ -22,8 +22,8 @@ # #################################################################### from fife import fife -from scripts.common.helpers import normalize -from scripts.common.helpers import Rect +from fife.extensions.fife_math import normalize +from fife.extensions.fife_math import Rect SHTR_DEFAULT = 0 diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/common/helpers.py --- a/demos/shooter/scripts/common/helpers.py Thu May 06 19:34:21 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -# -*- coding: utf-8 -*- - -# #################################################################### -# Copyright (C) 2005-2010 by the FIFE team -# http://www.fifengine.net -# This file is part of FIFE. -# -# FIFE is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -# #################################################################### - -from fife import fife -import math - - -def normalize(vector): - """ - Helper function to normalize a vector - - @param vector a fife.DoublePoint() to be normalized - - @return A normalized fife.DoublePoint() - """ - norm = fife.DoublePoint(0,0) - - invLength = 1.0/vector.length() - if invLength > 1e-06: - norm.x = vector.x * invLength; - norm.y = vector.y * invLength; - else: - norm.x = 0 - norm.y = 0 - - return norm - -class Rect(object): - """ - Rect - - A class used to specify the bounding box of objects. For use - with collision detection. - """ - def __init__(self, x = 0, y = 0, w = 0, h = 0): - """ - @param x The x coordinate - @param y The y coordinate - @param w The width - @param h The height - """ - self._x = x - self._y = y - self._w = w - self._h = h - - def intersects(self, rect): - """ - Returns if the rect intersects with this Rect. - - @param rect the Rect to perform the test against - """ - _x = self._x - rect.x; - _y = self._y - rect.y; - _w = self._w; - _h = self._h; - - if _x < 0: - _w += _x - _x = 0 - - if _y < 0: - _h += _y - _y = 0 - - if _x + _w > rect.w: - _w = rect.w - _x - - if _y + _h > rect.h: - _h = rect.h - _y - - if _w <= 0 or _h <= 0: - return False - - return True - - def _setX(self, x): - self._x = x - - def _getX(self): - return self._x - - def _setY(self, y): - self._y = y - - def _getY(self): - return self._y - - def _setW(self, w): - self._w = w - - def _getW(self): - return self._w - - def _setH(self, h): - self._h = h - - def _getH(self): - return self._h - - x = property(_getX, _setX) - y = property(_getY, _setY) - w = property(_getW, _setW) - h = property(_getH, _setH) - -def rotatePoint(origin, point, angle): - """ - Rotates a point around the specified origin. - - @param origin A fife.DoublePoint() specifying the origin - @param point A fife.DoublePoint() to be rotated - @param angle The angle in which to rotate the point - - @return A fife.DoublePoint() representing the rotated point - """ - newp = fife.DoublePoint(0,0) - - theta = (angle * math.pi)/180 - - costheta = math.cos(theta) - sintheta = math.sin(theta) - - x = point.x - origin.x - y = point.y - origin.y - - newp.x = costheta * x - sintheta * y - newp.y = sintheta * x + costheta * y - - return newp - -class Timer(fife.TimeEvent): - """ - Timer - - This class wraps the fife.TimeEvent class to make it easily usable from Python - It allows for a TimeEvent to be executed once or multiple times. - """ - def __init__(self,manager, delay=0,callback=None,repeat=0): - """ - @param manager The FIFE time manager - @param delay The delay in milliseconds to execute the callback - @param callback The function to execute - @param repeat The number of times to execute the callback. 1=once, 0=forever - """ - super(Timer,self).__init__(delay) - self._is_registered = False - self._callback = callback - self._manager = manager - self.setPeriod(delay) - self._repeat = repeat - self._executed = 0 - - def start(self): - """ - Must be called before the timer will start - """ - if self._is_registered: - return - self._is_registered = True - self._executed = 0 - self._manager.registerEvent(self) - - def stop(self): - """ - Stops the timer - """ - if not self._is_registered: - return - self._is_registered = False - self._manager.unregisterEvent(self) - - def updateEvent(self,delta): - """ - Should not be called directly. This is called by FIFE. - """ - if callable(self._callback): - self._callback() - - if self._repeat != 0: - self._executed += 1 - if self._executed >= self._repeat: - self.stop() - - diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/powerups.py --- a/demos/shooter/scripts/powerups.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/powerups.py Fri May 07 21:07:27 2010 +0000 @@ -48,11 +48,11 @@ self._velocity.x = -0.25 self._velocity.y = 0 - self._pickupclip = self._scene.soundmanager.loadSoundClip("sounds/pickup.ogg") + self._pickupclip = self._scene.soundmanager.createSoundEmitter("sounds/pickup.ogg") def applyPowerUp(self, ship): ship.weapon = CannonSpread5(self._scene, ship, 300) - self._scene.soundmanager.playClip(self._pickupclip) + self._pickupclip.play() self.destroy() self._scene.queueObjectForRemoval(self) @@ -78,11 +78,11 @@ def __init__(self, scene, powerupName, instance, findInstance=True): super(ExtraLifePU, self).__init__(scene, powerupName, instance, findInstance) - self._pickupclip = self._scene.soundmanager.loadSoundClip("sounds/pickup.ogg") + self._pickupclip = self._scene.soundmanager.createSoundEmitter("sounds/pickup.ogg") def applyPowerUp(self, ship): ship.lives += 1 - self._scene.soundmanager.playClip(self._pickupclip) + self._pickupclip.play() self.destroy() self._scene.queueObjectForRemoval(self) diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/scene.py --- a/demos/shooter/scripts/scene.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/scene.py Fri May 07 21:07:27 2010 +0000 @@ -26,7 +26,7 @@ from scripts.ships.player import Player from scripts.ships.enemies import * from scripts.powerups import * -from scripts.common.helpers import Rect +from fife.extensions.fife_math import Rect class SceneNode(object): """ @@ -209,7 +209,7 @@ #and finally add the player to the scene self.addObjectToScene(self._player) - self._music = self._soundmanager.loadSoundClip("music/waynesmind2.ogg") + self._music = self._soundmanager.createSoundEmitter("music/waynesmind2.ogg") self._music.callback = self.musicHasFinished self._music.looping = True self._soundmanager.playClip(self._music) diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/ships/enemies.py --- a/demos/shooter/scripts/ships/enemies.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/ships/enemies.py Fri May 07 21:07:27 2010 +0000 @@ -24,7 +24,7 @@ from fife import fife from scripts.ships.shipbase import * from scripts.common.baseobject import * -from scripts.common.helpers import Rect +from fife.extensions.fife_math import Rect from scripts.weapons import * @@ -211,7 +211,7 @@ self.hitpoints = 30 self.scorevalue = 1000 - self._explodclip = self._scene.soundmanager.loadSoundClip("sounds/bossexplode.ogg") + self._explodclip = self._scene.soundmanager.createSoundEmitter("sounds/bossexplode.ogg") def endLevel(self): self._scene.endLevel() diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/ships/player.py --- a/demos/shooter/scripts/ships/player.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/ships/player.py Fri May 07 21:07:27 2010 +0000 @@ -24,7 +24,7 @@ from fife import fife from scripts.common.baseobject import * from scripts.ships.shipbase import * -from scripts.common.helpers import * +from fife.extensions.fife_math import * from scripts.weapons import * @@ -112,7 +112,7 @@ def destroy(self): if not self._invulnerable and not self._dead: self._instance.act('explode', self._instance.getFacingLocation()) - self._scene.soundmanager.playClip(self._explodclip) + self._explodclip.play() self._dead = True self._invulnerable = True self._lives -= 1 diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/ships/shipbase.py --- a/demos/shooter/scripts/ships/shipbase.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/ships/shipbase.py Fri May 07 21:07:27 2010 +0000 @@ -86,8 +86,8 @@ self._hitpoints = 0 self._scorevalue = 0 - self._hitclip = self._scene.soundmanager.loadSoundClip("sounds/hit.ogg") - self._explodclip = self._scene.soundmanager.loadSoundClip("sounds/explode.ogg") + 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 @@ -127,7 +127,7 @@ if self._hitpoints <= 0: self.destroy() else: - self._scene.soundmanager.playClip(self._hitclip) + self._hitclip.play() def destroy(self): """ @@ -135,7 +135,7 @@ """ if self._running: self._instance.act('explode', self._instance.getFacingLocation()) - self._scene.soundmanager.playClip(self._explodclip) + self._explodclip.play() super(Ship, self).destroy() def _getHitPoints(self): diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/soundmanager.py --- a/demos/shooter/scripts/soundmanager.py Thu May 06 19:34:21 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,240 +0,0 @@ -# -*- coding: utf-8 -*- - -# #################################################################### -# Copyright (C) 2005-2010 by the FIFE team -# http://www.fifengine.net -# This file is part of FIFE. -# -# FIFE is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -# #################################################################### - -from fife import fife - -from scripts.common.helpers import Timer -from fife.extensions.pychan.tools import callbackWithArguments as cbwa - -class SoundClip(object): - """ - SoundClip - - This class stores an instance of a FIFE SoundEmitter class along - with some information about a sound clip (like gain and if its - looping). All instances of SoundClip should be created by SoundManager. - """ - def __init__(self, soundmanager, clipid, soundname, emitter): - """ - @param soundmanager A reference to the SoundManager - @param clipid The FIFE sound clip ID from the sound clip pool - @param soundname The filename of the sound - @param emitter A reference to the FIFE SoundEmitter associated with this clip - - """ - self._soundmanager = soundmanager - self._name = soundname - - #The FIFE SoundEmitter associated with this SoundClip. - #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 - - def _getClipID(self): - return self._fifeclipid - - def _getGain(self): - return self._gain - - def _setGain(self, gain): - 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: - self._fifeemitter.thisown = 0 - - def _getName(self): - return self._name - - def _getCallback(self): - return self._callback - - def _setCallback(self, 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 - - timer = property(_getTimer, _setTimer) - clipid = property(_getClipID) - gain = property(_getGain, _setGain) - looping = property(_getLooping, _setLooping) - fifeemitter = property(_getFifeEmitter, _setFifeEmitter) - name = property(_getName) - callback = property(_getCallback, _setCallback) - duration = property(_getDuration, _setDuration) - -class SoundManager(object): - """ - SoundManger - - This class manages and plays all the sounds of the game. - It creates SoundClips and ensures that there is only one - FIFE SoundEmitter per unique sound. - """ - def __init__(self, engine): - """ - @param engine A reference to the FIFE engine - """ - self._engine = engine - - self._fifesoundmanager = self._engine.getSoundManager() - self._fifesoundmanager.init() - - #A dict of fife emitters - self._loadedclips = {} - - def loadSoundClip(self, filename): - """ - Returns a valid SoundClip instance. - - @param filename the relative path and filename of the sound file - - @return Returns a new SoundClip instance. - """ - if not self._loadedclips.has_key(filename): - clipid = self._engine.getSoundClipPool().addResourceFromFile(filename) - fifeemitter = self._fifesoundmanager.createEmitter() - fifeemitter.thisown = 0 - fifeemitter.setSoundClip(clipid) - - self._loadedclips[filename] = fifeemitter - clip = SoundClip(self, clipid, filename, fifeemitter) - clip.duration = fifeemitter.getDuration() - else: - fifeemitter = self._loadedclips[filename] - clip = SoundClip(self, fifeemitter.getID(), filename, fifeemitter) - clip.duration = fifeemitter.getDuration() - - return clip - - def playClip(self, clip): - """ - Plays a sound clip. - - This function does not use the FIFE - emitters "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 SoundClip is invalid (no fifeemitter) then - it attempts to load it before playing it. - - Note that this will stop any clips that use the same - FIFE emitter. You cannot play the same sound more than - once at a time. - - @param clip The SoundClip to be played - """ - - if clip.fifeemitter: - if clip.callback: - if clip.timer: - clip.timer.stop() - timer = None - - if clip.looping: - repeat = 0 - def real_callback(c, e, g): - c() - e.stop() - e.setGain(g) - e.play() - - clip.callback = cbwa(real_callback, clip.callback, clip.fifeemitter, clip.gain) - - else: - repeat = 1 - - clip.timer = Timer(self._engine.getTimeManager(), clip.duration, clip.callback, repeat) - clip.timer.start() - - clip.fifeemitter.setGain(clip.gain) - clip.fifeemitter.play() - else: - clip = self.loadSoundClip(clip.name) - self.playClip(clip) - - def stopClip(self, clip): - """ - Stops playing the sound clip. Note that this will - affect all clips that use the same FIFE emitter. - - @parm clip The SoundClip to stop. - """ - if clip.fifeemitter: - clip.fifeemitter.stop() - - if clip.timer: - clip.timer.stop() - clip.timer = None - - def stopAllSounds(self): - for emitter in self._loadedclips.values(): - emitter.stop() - - def destroy(self): - """ - Releases all FIFE emitters. This does not free the resources - from the FIFE sound clip pool. - """ - self.stopAllSounds() - - for emitter in self._loadedclips.values(): - self._fifesoundmanager.releaseEmitter(emitter.getID()) - emitter = None - - self._loadedclips.clear() diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/weapons.py --- a/demos/shooter/scripts/weapons.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/weapons.py Fri May 07 21:07:27 2010 +0000 @@ -23,8 +23,7 @@ from fife import fife from scripts.common.baseobject import * -from scripts.common.helpers import normalize, rotatePoint -from scripts.soundmanager import * +from fife.extensions.fife_math import normalize, rotatePoint class Projectile(SpaceObject): """ @@ -133,7 +132,7 @@ super(Cannon, self).__init__(scene, ship, firerate) self._projectileVelocity = 0.75 - self._soundclip = scene.soundmanager.loadSoundClip("sounds/cannon.ogg") + self._soundclip = scene.soundmanager.createSoundEmitter("sounds/cannon.ogg") def fire(self, direction): @@ -147,14 +146,14 @@ self._lastfired = self._scene.time self._scene.addObjectToScene(pjctl) if self._soundclip: - self._scene.soundmanager.playClip(self._soundclip) + self._soundclip.play() class FireBall(Weapon): def __init__(self, scene, ship, firerate): super(FireBall, self).__init__(scene, ship, firerate) self._projectileVelocity = 0.50 - self._soundclip = scene.soundmanager.loadSoundClip("sounds/fireball.ogg") + self._soundclip = scene.soundmanager.createSoundEmitter("sounds/fireball.ogg") def fire(self, direction): velocity = normalize(direction) @@ -167,14 +166,14 @@ self._lastfired = self._scene.time self._scene.addObjectToScene(pjctl) if self._soundclip: - self._scene.soundmanager.playClip(self._soundclip) + self._soundclip.play() class FireBallBurst(Weapon): def __init__(self, scene, ship, firerate, burstrate, burstnumber): super(FireBallBurst, self).__init__(scene, ship, firerate) self._projectileVelocity = 0.50 - self._soundclip = scene.soundmanager.loadSoundClip("sounds/fireball.ogg") + self._soundclip = scene.soundmanager.createSoundEmitter("sounds/fireball.ogg") self._burstrate = burstrate self._burstnumber = int(burstnumber) @@ -195,7 +194,7 @@ self._scene.addObjectToScene(pjctl) if self._soundclip: - self._scene.soundmanager.playClip(self._soundclip) + self._soundclip.play() self._lastburstfired = self._scene.time self._burstcount -= 1 @@ -211,7 +210,7 @@ super(FireBallSpread, self).__init__(scene, ship, firerate) self._projectileVelocity = 0.50 - self._soundclip = scene.soundmanager.loadSoundClip("sounds/fireball.ogg") + self._soundclip = scene.soundmanager.createSoundEmitter("sounds/fireball.ogg") def fire(self, direction): @@ -259,7 +258,7 @@ self._scene.addObjectToScene(pjctl7) if self._soundclip: - self._scene.soundmanager.playClip(self._soundclip) + self._soundclip.play() self._lastfired = self._scene.time @@ -268,7 +267,7 @@ super(CannonSpread5, self).__init__(scene, ship, firerate) self._projectileVelocity = 1 - self._soundclip = scene.soundmanager.loadSoundClip("sounds/cannon.ogg") + self._soundclip = scene.soundmanager.createSoundEmitter("sounds/cannon.ogg") def fire(self, direction): @@ -306,7 +305,7 @@ self._scene.addObjectToScene(pjctl6) if self._soundclip: - self._scene.soundmanager.playClip(self._soundclip) + self._soundclip.play() self._lastfired = self._scene.time diff -r c4168eb47a44 -r 16ceb3228324 demos/shooter/scripts/world.py --- a/demos/shooter/scripts/world.py Thu May 06 19:34:21 2010 +0000 +++ b/demos/shooter/scripts/world.py Fri May 07 21:07:27 2010 +0000 @@ -26,9 +26,9 @@ import math, random from fife.extensions import pychan from fife.extensions.pychan import widgets +from fife.extensions.soundmanager import SoundManager from scripts.common.eventlistenerbase import EventListenerBase -from scripts.common.helpers import normalize from fife.extensions.loaders import loadMapFile from scripts.gui.guis import * @@ -36,7 +36,6 @@ from scripts.ships.shipbase import Ship from scripts.ships.player import Player from scripts.scene import Scene -from scripts.soundmanager import SoundManager class World(EventListenerBase): """ diff -r c4168eb47a44 -r 16ceb3228324 engine/python/fife/extensions/__init__.py --- a/engine/python/fife/extensions/__init__.py Thu May 06 19:34:21 2010 +0000 +++ b/engine/python/fife/extensions/__init__.py Fri May 07 21:07:27 2010 +0000 @@ -9,4 +9,6 @@ 'filebrowser', 'pythonize', 'savers', -] \ No newline at end of file + 'soundmanager', + 'fife_math' +] diff -r c4168eb47a44 -r 16ceb3228324 engine/python/fife/extensions/fife_math.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/python/fife/extensions/fife_math.py Fri May 07 21:07:27 2010 +0000 @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- + +# #################################################################### +# Copyright (C) 2005-2010 by the FIFE team +# http://www.fifengine.net +# This file is part of FIFE. +# +# FIFE is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# #################################################################### + +from fife import fife +import math + +""" +Math Library +================================== + +This is a collection of useful 2D math functions/classes. +""" + + +def normalize(vector): + """ + Helper function to normalize a 2D vector + + @param vector a L{fife.DoublePoint} to be normalized + + @return A normalized L{fife.DoublePoint} + """ + norm = fife.DoublePoint(0,0) + + invLength = 1.0/vector.length() + if invLength > 1e-06: + norm.x = vector.x * invLength; + norm.y = vector.y * invLength; + else: + norm.x = 0 + norm.y = 0 + + return norm + +class Rect(object): + """ + Rect + + A class used to specify the bounding box of objects. For use + with collision detection. This was written in python because + FIFE does not provide a Rect class that can use floating point + values. + """ + def __init__(self, x = 0, y = 0, w = 0, h = 0): + """ + @param x The x coordinate + @param y The y coordinate + @param w The width + @param h The height + """ + self._x = x + self._y = y + self._w = w + self._h = h + + def intersects(self, rect): + """ + Tests for intersection of rect. + + @param rect the Rect to perform the test against + @return True if the rectancles intersect, False if not. + """ + _x = self._x - rect.x; + _y = self._y - rect.y; + _w = self._w; + _h = self._h; + + if _x < 0: + _w += _x + _x = 0 + + if _y < 0: + _h += _y + _y = 0 + + if _x + _w > rect.w: + _w = rect.w - _x + + if _y + _h > rect.h: + _h = rect.h - _y + + if _w <= 0 or _h <= 0: + return False + + return True + + def _setX(self, x): + self._x = x + + def _getX(self): + return self._x + + def _setY(self, y): + self._y = y + + def _getY(self): + return self._y + + def _setW(self, w): + self._w = w + + def _getW(self): + return self._w + + def _setH(self, h): + self._h = h + + def _getH(self): + return self._h + + x = property(_getX, _setX) + y = property(_getY, _setY) + w = property(_getW, _setW) + h = property(_getH, _setH) + +def rotatePoint(origin, point, angle): + """ + Rotates a point around the specified origin. + + @param origin A L{fife.DoublePoint} specifying the origin. + @param point A L{fife.DoublePoint} to be rotated. + @param angle The angle in which to rotate the point. + + @return A L{fife.DoublePoint} representing the rotated point. + """ + newp = fife.DoublePoint(0,0) + + theta = (angle * math.pi)/180 + + costheta = math.cos(theta) + sintheta = math.sin(theta) + + x = point.x - origin.x + y = point.y - origin.y + + newp.x = costheta * x - sintheta * y + newp.y = sintheta * x + costheta * y + + return newp + +__all__ = ['normalize','Rect','rotatePoint'] diff -r c4168eb47a44 -r 16ceb3228324 engine/python/fife/extensions/fife_timer.py --- a/engine/python/fife/extensions/fife_timer.py Thu May 06 19:34:21 2010 +0000 +++ b/engine/python/fife/extensions/fife_timer.py Fri May 07 21:07:27 2010 +0000 @@ -28,22 +28,21 @@ ================= Usage:: - import timer - timer.init( my_fife_engine.getTimeManager() ) + import fife.extensions.fife_timer + fife_timer.init( my_fife_engine.getTimeManager() ) def spam(): print "SPAM SPAM ", - return "More spam?" # a string is a true value, so it's repeated. - repeater = timer.repeatCall(500,spam) + repeater = fife_timer.repeatCall(500,spam) def stop_spam(): repeater.stop() print "BACON EGGS AND SPAM" - timer.delayCall(50000,stop_spam) + fife_timer.delayCall(50000,stop_spam) """ _manager = None -_alltimers = {} +_alltimers = [] def init(timemanager): """ @@ -55,32 +54,63 @@ _manager = timemanager class Timer(fife.TimeEvent): - def __init__(self,delay=0,callback=None): - super(Timer,self).__init__(0) - self.manager = _manager - self.is_registered = False - self.callback = callback + """ + Timer + + This class wraps the fife.TimeEvent class to make it easily usable from Python + It allows for a TimeEvent to be executed once or multiple times. + """ + def __init__(self,delay=0,callback=None,repeat=0): + """ + @param delay The delay in milliseconds to execute the callback + @param callback The function to execute + @param repeat The number of times to execute the callback. 1=once, 0=forever + """ + super(Timer,self).__init__(delay) + self._is_registered = False + self._callback = callback + self._manager = _manager self.setPeriod(delay) + self._repeat = repeat + self._executed = 0 def start(self): - if self.is_registered: + """ + Must be called before the timer will start + """ + if self._is_registered: return - self.is_registered = True + self._is_registered = True + self._executed = 0 + self._manager.registerEvent(self) + global _alltimers - _alltimers[self]=1 - self.manager.registerEvent(self) + _alltimers.append(self) def stop(self): - if not self.is_registered: + """ + Stops the timer + """ + if not self._is_registered: return - self.is_registered = False + self._is_registered = False + self._manager.unregisterEvent(self) + global _alltimers - del _alltimers[self] - self.manager.unregisterEvent(self) + _alltimers.remove(self) + def updateEvent(self,delta): - if callable(self.callback): - self.callback() + """ + Should not be called directly. This is called by FIFE. + """ + if callable(self._callback): + self._callback() + + if self._repeat != 0: + self._executed += 1 + if self._executed >= self._repeat: + self.stop() def delayCall(delay,callback): """ @@ -91,18 +121,11 @@ @return The timer. """ - timer = Timer(delay) - - def real_callback(c, t): - t.stop() - c() - - from fife.extensions.pychan.tools import callbackWithArguments as cbwa - timer.callback = cbwa(real_callback, callback, timer) + timer = Timer(delay, callback, 1) timer.start() return timer -from traceback import print_exc + def repeatCall(period,callback): """ Repeat a function call. @@ -112,21 +135,11 @@ @return The timer. - The call is repeated until the callback returns a False - value (i.e. None) or the timer is stopped. + The call is repeated until the timer is stopped. """ - timer = Timer(period) - def real_callback(): - try: - if not callback(): - timer.stop() - except Exception: - print_exc() - timer.stop() - - timer.callback = real_callback + timer = Timer(period, callback, 0) timer.start() return timer -__all__ = [init,Timer,delayCall,repeatCall] +__all__ = ['init','Timer','delayCall','repeatCall'] diff -r c4168eb47a44 -r 16ceb3228324 engine/python/fife/extensions/soundmanager.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/python/fife/extensions/soundmanager.py Fri May 07 21:07:27 2010 +0000 @@ -0,0 +1,277 @@ +# -*- coding: utf-8 -*- + +# #################################################################### +# Copyright (C) 2005-2010 by the FIFE team +# http://www.fifengine.net +# This file is part of FIFE. +# +# FIFE is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# #################################################################### + +from fife import fife + +import fife.extensions.fife_timer as fife_timer +from fife.extensions.pychan.tools import callbackWithArguments as cbwa + +""" +Sound Manager +================================== + +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 +a good starting point for a more advanced version of a sound manager. + +""" + +class SoundEmitter(object): + """ + SoundEmitter + + 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. + """ + def __init__(self, soundmanager, clipid, soundname, emitter): + """ + @param soundmanager A reference to the SoundManager + @param clipid The FIFE sound clip ID from the sound clip pool + @param soundname The filename of the sound + @param emitter A reference to the L{fife.SoundEmitter} associated with this clip + + """ + 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 + + 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): + 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: + self._fifeemitter.thisown = 0 + + def _getName(self): + return self._name + + def _getCallback(self): + return self._callback + + def _setCallback(self, 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 + + timer = property(_getTimer, _setTimer) + clipid = property(_getClipID) + gain = property(_getGain, _setGain) + looping = property(_getLooping, _setLooping) + fifeemitter = property(_getFifeEmitter, _setFifeEmitter) + name = property(_getName) + callback = property(_getCallback, _setCallback) + duration = property(_getDuration, _setDuration) + +class SoundManager(object): + """ + SoundManger + + 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): + """ + @param engine A reference to the FIFE engine + """ + + self._engine = engine + + self._fifesoundmanager = self._engine.getSoundManager() + self._fifesoundmanager.init() + + #A dict of fife emitters + self._loadedclips = {} + + def createSoundEmitter(self, filename, forceUnique=False): + """ + Returns a valid SoundEmitter instance. + + @param filename The relative path and filename of the sound file + @parm 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 + to be played at the same time. + + @return Returns a new SoundEmitter instance. + """ + if not self._loadedclips.has_key(filename): + clipid = self._engine.getSoundClipPool().addResourceFromFile(filename) + fifeemitter = self._fifesoundmanager.createEmitter() + fifeemitter.thisown = 0 + fifeemitter.setSoundClip(clipid) + + self._loadedclips[filename] = [fifeemitter] + clip = SoundEmitter(self, clipid, filename, fifeemitter) + clip.duration = fifeemitter.getDuration() + else: + if forceUnique: + clipid = self._engine.getSoundClipPool().addResourceFromFile(filename) + fifeemitter = self._fifesoundmanager.createEmitter() + fifeemitter.thisown = 0 + fifeemitter.setSoundClip(clipid) + self._loadedclips[filename].append(fifeemitter) + else: + fifeemitter = self._loadedclips[filename][0] + + clip = SoundEmitter(self, fifeemitter.getID(), filename, fifeemitter) + clip.duration = fifeemitter.getDuration() + + return clip + + def playClip(self, clip): + """ + Plays a sound clip. + + This function does not use the L{fife.SoundEmitter} + "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 + 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 SoundEmitter to be played + """ + + if clip.fifeemitter: + if clip.callback: + if clip.timer: + clip.timer.stop() + timer = None + + if clip.looping: + repeat = 0 + def real_callback(c, e, g): + c() + e.stop() + e.setGain(g) + e.play() + + clip.callback = cbwa(real_callback, clip.callback, clip.fifeemitter, clip.gain) + + else: + repeat = 1 + + clip.timer = fife_timer.delayCall(clip.duration, clip.callback) + #clip.timer.start() + + clip.fifeemitter.setGain(clip.gain) + clip.fifeemitter.play() + 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 + use the same FIFE emitter. + + @parm clip The SoundEmitter to stop. + """ + if clip.fifeemitter: + clip.fifeemitter.stop() + + if clip.timer: + clip.timer.stop() + clip.timer = None + + def stopAllSounds(self): + for emitterlist in self._loadedclips.values(): + for emitter in emitterlist: + emitter.stop() + + def destroy(self): + """ + Releases all instances of L{fife.SoundEmitter}. 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() + +__all__ = ['SoundEmitter','SoundManager'] diff -r c4168eb47a44 -r 16ceb3228324 setup.py --- a/setup.py Thu May 06 19:34:21 2010 +0000 +++ b/setup.py Fri May 07 21:07:27 2010 +0000 @@ -35,7 +35,7 @@ setup(name='fife', version='0.3.1', description='Flexible Isometric Free Engine', - url='www.fifengine.de', + url='www.fifengine.net', packages = ['fife', 'fife.extensions', 'fife.extensions.pychan', 'fife.extensions.pychan.widgets', 'fife.extensions.pychan.widgets.ext', 'fife.extensions.serializers' ], package_dir = { '': os.path.join('engine','python') }, package_data = pkg_data,