When I have tons of sounds playing, sometimes the sounds don’t work when I play them. I don’t mind this happening for the explosion sounds and such, but there are certain sounds, such as leveling up, which I do want to be heard. How can I make these sounds play, even at times where lots of sounds are happening?
Overriding/Getting-around Sound Limit
i’m gonna try to write here something, but i’m sure there’ll be some or much mistakes in my code, but, you can understand what i mean with this…
need a global boolean variable like “importantsounds:int = 0” to check if there is an important sound playing around…
then go to your main sfx class and add a boolean and number variable and a parameter to play function
private var important:Boolean;
private var defaultvolume:Number = -1;
play(vol:Number = 1, pan:Number = 0, important:Boolean = false);
{
if (important)
{
this.important = important;
GLOBALS.importantsounds++;
}
}
//and go to update function,
update()
{
if (!this.important && GLOBALS.importantsounds > 0)
{
if (defaultvolume == -1) defaultvolume = _volume;
_volume = defaultvolume*0.5;
}
else if(this.defaultvolume != -1) _volume = this.defaultvolume;
}
//and go to onComplete function in sfx
onComplete(.....)
{
if (this.important) GLOBALS.importantsounds--;
}
or you can duplicate your main sfx class as “sfx2” and you can use this class for not important sounds, so you can check global important sounds variable inside only this class, and you can control this global variable with orginal sfx class, it’ll be easier and makes better performance but i don’t know is two sfx classes works properly in the same time…
there are some stuff like that in the main sfx class,
/** @private */ private static var _sounds:Dictionary = new Dictionary;
/** @private */ private static var _typePlaying:Dictionary = new Dictionary;
/** @private */ private static var _typeTransforms:Dictionary = new Dictionary;
i feel this stuff can help you best about that, but i don’t know how to use them right now, so, i think you don’t use my ways, it is better you wait for someone who knows better…
Your main problem is probably that Flash only allows 32 sounds to be playing simultaneously. There are a few ways you can work around this, but the bottom line is that there’s no way to trick the Flash Player into giving you more sounds.
The first way is to use a pool. Instead of creating a new Sfx object every time you want an explosion to sound off, keep a list of sounds and recycle them. Here’s an example:
var explosions:Array = [];
for (var i:int = 0; i < MAX_EXPLOSIONS; ++i)
{
explosions.push(new Sfx(EXPLODE)),
}
When you want something to explode, search the array to find an instance that isn’t currently playing, and use that instead. If none of the sounds are available, find the one that’s the closest to being finished, stop it, and then start it again.
function playExplosion():void
{
var furthest:Sfx = null;
var max:Number = 0;
for each (var sound:Sfx in explosions)
{
if (!sound.playing)
{
sound.play();
break;
}
else
{
if (sound.position > max)
{
furthest = sound;
max = sound.position;
}
}
}
if (furthest != null)
{
furthest.stop();
furthest.play();
}
}
If there’s enough going on your player won’t even notice the change.
If you can post a simple project that shows the issue I’ll be more than happy to play (hehe) around with it and try to find a solution. I could write it myself but I am laaazy so…
As @AlobarNon said it would probably require to hack the SFX
class (but maybe not). From what I can see a possible workaround would be to hold a reference to your explosions sounds playing and force one/many of them to stop if an important sounds doesn’t start, or simply limit the unimportant ones to a number below 32 (which should be the maximum numbers of sounds playing at once IIRC).
Something like (untested):
const MAX_UNIMPORTANT_SOUNDS:int = 26;
var unimportantSounds:int = 0;
function playSound(sfx:Sfx, important:Boolean = false, vol:Number = 1, pan:Number = 0):Boolean {
var unimportantAvailable:Boolean = !important && unimportantSounds < MAX_UNIMPORTANT_SOUNDS;
if (unimportantAvailable) {
unimportantSounds++;
sfx.complete = function() { unimportantSounds--; };
}
if (unimportantAvailable || important) {
sfx.play(vol, pan);
}
return sfx.playing; // return true if sfx is now actually playing
}
...
playSound(explosionSfx, false);
playSound(levelUpSfx, true);
Ohh: Didn’t see @jacobalbano replied while I was writing this. Now you have some choice!
Another possible problem is simply that your existing sounds are so loud that the important ones can’t be heard over the ruckus. If that’s the case, the solution is simple. You can assign each of your sounds a type, and then lower the volume of all sounds in that group with setVolume().
Flashpunk doesn’t have an automatic “ducking” system like some other game engines, but it’s reasonably simple to do on your own. Hope that helps!
Hey, remember array cloning problem, what if we create a new array and push number objects inside it for all sound types then assign this array’s elements to every created sfx class’s volume level number variable like if(type=“music”) array[0] = this.volume; if(type=“bullet”) array[1] = this.volume; if(type=“explode”) array[1] = this.volume;
then we can mix volume levels easily by only changing values in the array? is it works easy like that? or need much work?
That’s one approach but the Sfx class already handles that for you. No need to reinvent it.
I don’t know if this is the right place to put something like this, but for a future update, the Sfx
class should probably keep an internal counter of sounds playing and then output a warning to the console if you exceed 32.
It would be even better if it took out older sounds to make room for new ones (with an option to not do this), but that might be too much for a minor version update.
I’ve encountered this problem and I had no idea what was causing it so I just decided to live with it. A simple console message would have clued me in to the problem and I could have fixed it (I’ll probably go back and fix it now, though.)
I’ll submit a pull request when I have time. Let me know if you have thoughts/opinions regarding this.
Thank you all for the help! Well, the issue is that I’m going over the 32 sound limit. I can tell this for sure, as the volume is not the issue. But the idea of using an array is good.
I’m going to write myself a sound manager class. Was wondering, if I start music in one world, then change the world, and pass an array to the new world which contains the SFX object within it, will it allow me to stop it, or does the reference die with the old world??
Here is my solution class if anyone is wondering. It is very basic atm, will add fade in and fade out function to it as well.
package
{ /** * … * @author FRAZER BENNETT WILFORD */
import net.flashpunk.Entity;
import net.flashpunk.Sfx;
public class SoundM extends Entity
{
////////////////////////////////
//// SONG 1 - RELAX MENU
[Embed(source="/assets/Sound Effects/554008_I-Remember-Her-8-Bi.mp3")] private const LOOP0:Class;
public var loop0:Sfx = new Sfx(LOOP0);
//// Exp Bar Progress
[Embed(source = "assets/Sound Effects/leveling1.mp3")] private const LOOP1:Class;
public var loop1:Sfx = new Sfx(LOOP1);
/// Typing Sound
[Embed(source="assets/Sound Effects/typing.mp3")] private const LOOP2:Class;
public var loop2:Sfx = new Sfx(LOOP2);
public var loop_array:Array = [loop0, loop1, loop2];
//// FX
/// Click Sound # 1
[Embed(source="/assets/Sound Effects/click3.mp3")] private const FX0:Class;
/// Into Planet Sound #1 - SHEILD
[Embed(source = "assets/Sound Effects/Shield_damage.mp3")] private const FX1:Class;
/// Into Planet Sound #1
[Embed(source="assets/Sound Effects/IntoPlanet.mp3")] private const FX2:Class;
/// Achievment ACTIVATE
[Embed(source = "assets/Sound Effects/171670__fins__success-2.mp3")] private const FX3:Class;
/// Click on Planet
[Embed(source = "assets/Sound Effects/rollover1.mp3")] private const FX4:Class;
/// Hover Over Planet
[Embed(source = "assets/Sound Effects/rollover2.mp3")] private const FX5:Class;
/// LEVELED UP
[Embed(source = "assets/Sound Effects/171670__fins__success-2.mp3")] private const FX6:Class;
/// Activate Sound // intercom
[Embed(source = "assets/Sound Effects/204369__philitup321__alert-sound.mp3")] private const FX7:Class;
public var fx_array:Array = [FX0, FX1, FX2, FX3, FX4, FX5, FX6, FX7];
public var fx_playing:Array = [];
///////////////////////////////
public var MAX_SOUNDS:int = 30;
public var MAX_FX:int = 28;
public var current_sounds:int = 0;
public function SoundM()
{
name = "SoundM";
}
public function startLoop(loop:int,volume:Number):void
{
if ((loop_array[loop] as Sfx).playing == false)
{
current_sounds += 1;
(loop_array[loop] as Sfx).loop(volume);
}
}
public function stopLoop(loop:int):void
{
current_sounds -= 1;
(loop_array[loop] as Sfx).stop();
}
/////////////////////////////////////////
public function startFX(fx:int,volume:Number, overrideLIMIT:Boolean):void
{
removeCompleteFX();
if (fx_playing.length < MAX_FX || overrideLIMIT == true)
{
current_sounds += 1;
fx_playing.push(new Sfx(fx_array[fx]));
var new_sound:int = fx_playing.length - 1;
(fx_playing[new_sound] as Sfx).play(volume);
}
}
public function removeCompleteFX():void
{
trace(fx_playing.length);
for (var i:int = 0; i < fx_playing.length; i ++)
{
if ((fx_playing[i] as Sfx).playing == false)
{
current_sounds -= 1;
fx_playing.splice(i, 1);
}
}
trace(fx_playing.length);
}
}
}