I see most of the games I have played support this feature, ability to mute just music but not sound effects and/or mute sound effects but not music by will.
Phaser.SoundManager has the “mute” property but that mutes all sounds including music and effects.
I will have two buttons, one to mute just sound effects and one to mute just music.
Some ideas on how to achieve this? Or I need to implement some logic with the “onMute” event handler and set mute to false for specific audio files?
Hmm, I created global flags for muting sound effects and music. I also added helper methods for playing sound effects and music. These helper methods decide if they should play the sound on volume 0 or volume 1 or different. So now I call these helper methods with sound key and they return Phaser.Sound object as per muted or not muted sound effects or music flag. Something like this:
var
soundEffectsMuted = false,
musicMuted = false,
muteSoundEffects = function () {
soundEffectsMuted = true;
},
unMuteSoundEffects = function () {
soundEffectsMuted = false;
},
areSoundEffectsMuted = function () {
return soundEffectsMuted;
},
muteMusic = function () {
musicMuted = true;
},
unMuteMusic = function () {
musicMuted = false;
},
isMusicMuted = function () {
return musicMuted;
},
playSoundEffect = function (soundKey, volume) {
var soundEffect = null;
if(!soundEffectsMuted)
soundEffect = gameObject.sound.play(soundKey, volume, false);
else
soundEffect = gameObject.sound.play(soundKey, 0, false);
return soundEffect;
},
playMusic = function (musicKey, volume) {
var musicSound = null;
if(!musicMuted)
musicSound = gameObject.sound.play(musicKey, volume, true);
else
musicSound = gameObject.sound.play(musicKey, 0, true);
return musicSound;
}
So, you would play one music file per Phaser.State which probably be on loop. This is to make sure you know which sound file was played so you can stop that sound file on shutdown. I have forgotten to add the getter/setter methods for the music object.
getMusicSoundObject: function () {
return musicSoundObject;
},
setMusicSoundObject: function (musicSoundObjectObj) {
musicSoundObject = musicSoundObjectObj;
}
you can then call in shutdown
shutdown: function () {
this.getMusicSoundObject().stop();
}
this will make sure the music file you played is stopped.
In create() you would do:
this.setMusicSoundObject(phaserGame.Screen.playMusic('some music file key'));
Same would be for sound effects although effect are often short and are not looped.
Note: I have a basic JavaScript “inheritance scheme”. Generic class called “State” (not Phaser.State) and then class called “Screen” which inherits from “State”. Then all screens you build inherit from “Screen”. Say, “MainMenuScreen”, “OptionsScreen”, “LevelScreen”. Say you have some background subtle music on “MainMenuScreen”, “OptionsScreen” and then you play the level 1 music on “LevelScreen”. Since getMusicSoundObject() is part of “Screen” you would need to use setMusicSoundObject() in init on “MainMenuScreen”, “OptionsScreen” and “LevelScreen” to set the music object and then be able to stop it on shutdown, because it will continue playing.
But i do have reusable code in Screen which eases my work in other screens.
Thanks again! Looking forward to your update in case you’ll find sth. better.
Another question:
In the function variables you define for playSoundEffect and playMusic you are using a gameObject. How does this fit into the picture of that function collection?
Background is the following: I want to use your proposal as “generic” possibility to steer muting/unmuting in my project. But since I access my Phaser cache plainly via my scene instance (only have one scene as of now) I wonder how I can access it generally. As of now I can only think of either passing the scene in + the key to accesss the file from cache, or caller reads the file from cache and passes it directly.
(Sorry - still new to all that Phaser and JS stuff …)
gameObject is just another name for Phaser.Game in my code. I think you use
game.add.image(...) // or
game.add.graphics(...) // or
game.add.sprite(...)
to add objects on to the stage and “game.add” is of type Phaser.GameObjectFactory.
I still use JavaScript ES 5 and I have a function called namespace() which sort of helps me create JavaScript “inheritance”. But posting it here on this post would miss the point of the post. I might send it to you if you would like to check it.
But you don’t have to follow how I do things. You can also use JavaScript ES6 which has classes or you can go even further with Typescript which creates JavaScript code for you but you code with classes, inheritance etc…
There is no rule on how to code JavaScript as long as you include the scripts in the index.html page in the right order. You can create several Phaser.State objects in different files and they will work as long as they can see each other. But the Phaser.Game object must be in the first included script in the index.html
You can define the mute/unmute music and sound effect methods in the first scripts and all other scripts below in the index.html will be able to see it and use it.
Check this github page. I made it while ago. Might be able to help you: Phaser2Structure
Thank you. Seems Phaser 3 does not offer this anymore (using Phaser 3 - just posted to this thread since I was looking for a concept just like the one you posted).
But at least I can access the game cache in similar manner and hence access previously loaded sound files (loaded in preload and added in create method).
I haven’t check what changes Phaser 3, but the example code I posted is just a wrapper around the Phaser code so possibly can still be used with Phaser 3.
JavaScript, learn JavaScript. Those were defined inside a function as variables. It couldn’t find them i.e they were undefined, so I had to define them as variables.
I am on it (learning JS I mean), hence I read several posts, articles in the Web what’s the advantage of using function expressions assigned to variables compared to “plain” functions.
Scrolled up the thread again and looked at the code but could not find yet where those are defined as variables inside a function - e.g. for muteSoundEffects = function () { soundEffectsMuted = true; } and all the others I could not yet recognise that those function expressions are created within a function themselves. Just seeing the list of variable definitions by assignments. - What is the surrounding function in your case (really interested)?
I was thinking muteSoundEffects() etc. were considered also as globally available functions themselves - not being placed inside of another function…
Thank you. Already do so. - Was just my problem that I could not figure out from your initial post that everything was considered to be within a function and not just inside a class (but outside a function) or in a plain .js file (also outside of a function).
Also I phrased my question wrongly: Did not want to ask for the basics of function expressions vs “plain” functions but for the reasons why you used function expressions for your soundmanaging stuff. Chose the wrong verb accidentally in my question above (language barrier on my side does not make things easier).
So sorry for the misunderstanding - was of the opinion the sound managing parts are some external, globally accessible functions of a bigger ECS approach or so…
I recommend Douglas Crockford - JavaScript the good parts. It contains alot of JS examples on the good parts but bad parts as well. It covers ES5 standard. But it is rather old book and JS have improved alot. I still haven’t checked ES6 standard where classes exists. Somebody has told me that ES6 is just a “syntax sugar” over ES5, but I am not 100% sure.
This book covers the construct I mentioned, where you create a function, assign it to a variable and then anonymously call that same function. Returning object assigns that object to the variable. Finally, ES5 didn’t have private fields/methods. The only way to achieve those was to create them inside a function and then call getter/setter methods for them. This prevented from the fields being changed at runtime unsing F12 browser console.
If you prefer working this way.
If you check the Phaser sample project I posted, there are defining constants, but those existed only in “use strict” mode for ES5.
Pay attention to “addConstant()” and “namespace()” methods. You can create a file structure and JS/DOM object structure using the “namespace()” method and just include the files in the right order in index.html without using module loaders and such.