J’ai eu besoin pour Atomic Boarder d’ajouter du son et d’avoir une facade qui encapsule toute la gestion sonore.
Je vous propose de partager le noyau de cette classe qui peut servir sur n’importe quel projet (application ou jeu) et peut-être permettre à certains d’entre vous de comprendre les mécanismes et avantages offerts par un design de ce type.
Comme je l’avais déjà illustré à l’époque, l’objectif est simple et le principe efficace.
Il s’agit de créer une classe avec des membres statiques qui s’occupera d’instancier, de stocker et gérer un parc d’objets.
Au chapitre des avantages :
- Le fait de gérer l’instanciation et la destruction des objets au même endroit et d’offrir pour unique référence aux classes qui les utilisent un numéro d’id permet de bénéficier d’une propreté maximale. Les références sont virtuelles et coupées de l’objet lui-même au niveau du bytecode
- Offrir une une interface unique et bien encapsulée pour gérer un même type d’objets nous permet de pouvoir modifier à n’importe quel moment le fonctionnement interne de celle-ci pour ajouter ou enlever des fonctionnalités.
- Permettre tout ce qui est batch process, appliquer une même méthode à tous les objets du même type (ex : muteAllSounds() ). Réaliser des tris, des sous-groupes …
- Dernier point, ce type de classe peut être une manière habile pour éviter l’héritage abusif dans bien des cas. Rien de plus facile par exemple d’ajouter une méthode fade à un notre objet Sound en implémentant une méthode statique supplémentaire (à notre facade) du nom de makeFade qui prendra pour paramètre le numéro d’id du son concerné.
Assez parlé, voici une illustration basique :
class com.petepx.SoundFactory
{
private static var _bIsInitialized:Boolean = false;
private static var _oSounds:Object = new Object();
private static var _nCount:Number = 1;
private static var _oContainer:MovieClip;
private static var _bIsOn:Boolean = true;
private static var _noSound:Sound = _makeSound("", 0);
private function SoundFactory() {}
private static function _init(mcTarget:MovieClip) : Void
{
mcTarget == undefined ?_oContainer =
_level0.createEmptyMovieClip("__snd__", 65536) : _oContainer = mcTarget;
_bIsInitialized = true;
}
private static function _makeSound(linkageID:String, soundID:Number) : Sound
{
var container = _oContainer.createEmptyMovieClip("sound" + soundID, soundID);
var sound = new Sound(container);
sound.attachSound(linkageID);
return sound;
}
/* -------------------- */
public static function init(mcTarget:MovieClip) : Void { _init(mcTarget); }
public static function getSound(id:Number) : Sound
{
return _bIsOn ? _oSounds[id] : _noSound;
}
public static function removeSound(id:Number) : Void
{
_oContainer["sound" + id ].removeMovieClip();
delete _oSounds[id];
}
public static function addSound(linkageID:String) : Number
{
if (!_bIsInitialized) _init();
_oSounds[_nCount] = _makeSound(linkageID, _nCount);
_nCount++;
return _nCount - 1;
}
public static function addSounds(a:Array) : Void
{
for (var c=0; c< a.length; c++) addSound(a[c]);
}
public static function toggleOnOff() : Void { _bIsOn ? goOff() : goOn(); }
public static function get isOn() : Boolean { return _bIsOn; }
public static function goOn() : Void { _bIsOn = true; }
public static function goOff() : Void
{
_bIsOn = false;
stopAllSounds();
}
}
// Exemple d'utilisation
import com.petepx.SoundFactory;
// initialisation, purement optionnelle
SoundFactory.init(myMcLib);
// Ajouter une liste de sons en fournissant leurs linkages
SoundFactory.addSounds(['boom', 'crack', 'clang', 'dring']);
// On joue le son n°3 et on l'efface
SoundFactory.getSound(3).start();
SoundFactory.removeSound(3);
// On ajoute un son en récupérant son numéro d'id
var n:Number = SoundFactory.addSound('bong');
// On utilise l'id stocké pour pouvoir jouer le son associé
SoundFactory.getSound(n).start();
// On coupe le son de la factory
SoundFactory.goOff();















