Lets hear it! - That Invisible Trigger & Those Controls
Uncommented Code Version
---------------------------------------------------
// -- ACTOR DRIVEN PROXIMITY SOUND TRIGGER --
stage1 = stageModel.getSolidObject(0).rootPrimitive;
trigBox = stage1.find(".../sound-trigger");
soundPlaying = false; //Set a flag for our trick to stop sound restarting constantly inside trigger radius.
timestep=function()
{
if(player.dist(trigBox.position) < 6 && !soundPlaying)
{
soundPlaying = true;
trigSound.play();
}
else if (soundPlaying && player.dist(trigBox.position) >= 6)
{
soundPlaying = false;
}
}
---------------------------------------------------
Commented Code Version
---------------------------------------------------
//Earlier in the script this snippet came from, sound file was defined as "trigSound". Its sound properties were set.
//Remember that JavaScript is case sensitive. 'trigBox' and 'trigbox' are too different objects.
stage1 = stageModel.getSolidObject(0).rootPrimitive;
trigBox = stage1.find(".../sound-trigger"); //Find the box "sound-trigger" in main world. Remember it as "trigBox".
soundPlaying = false; //Set a flag so we know when the sound is playing. When we start our script, it is not.
//Now create a function to start the sound playing, but only once, when a player enters the perimeter.
timestep=function()
{
//Below, if the player is within (< means "less than") the perimeter distance of 6 feet from the box, AND (&& means "and")...
//...the sound is NOT (! means "not") already playing, then set the flag to 'true' and play the sound:
if(player.dist(trigBox.position) < 6 && !soundPlaying)
{
soundPlaying = true;
trigSound.play();
}
//But if the sound is already playing, AND (&&) the player is 6 feet or more (>= means "greater than or equal to") from...
//...the box, set the flag to 'false'.
else if (soundPlaying && player.dist(trigBox.position) >= 6)
{
soundPlaying = false;
}
}
How it Works
The logic: conditions and results
Okay, this is simple stuff for the intermediates and experts, but I wrote it all out for the rest of us. Hope I covered all the angles! It goes like this:
1. The player has never been, and is still not, within 6 feet of the trigger box:
Then the 'if' is false and is therefore not executed, because the player is not within 6 feet. Also the 'else' is false and is therefore not executed, because the sound is not already playing.
So, the code does nothing. This is a good thing.
2. The player enters the trigger perimeter:
The 'if' is now true, the player is inside the perimeter and the sound is not already playing.
Therefore, the flag is set to indicate that the sound is playing and indeed the sound is now played. The 'else' is false because the player is still inside the perimeter, so the flag stays at 'sound is playing'. With the flag still set to show that the sound is already playing, it cannot be started again. This is also good.
3. Player stays in the perimeter after the sound finishes:
Even though the sound has actually finished, nothing has happened to change the flag, so the 'if' is false. The 'else' is also false, because the player is still inside the perimeter. So, nothing happens and the sound does not play more than once. excellent - the problem is solved!
4. The player leaves the perimeter:
The 'if' is false, whether the sound is still playing or not, since the player is outside the perimeter. The 'else' is true if the sound is still playing. Therefore the flag is set to 'not playing'. This has no affect on the sound that is already playing. It will complete and then shut off. But it does reset the trigger for the next victim.
If the player leaves the perimeter after the sound completes, neither "if" nor "else" is run and the flag still shows the sound as playing - temporarily. But this causes no problem and the flag is reset to "false" with the next timestep (next displayed frame) of your world. That is what timesteps do for a living. That is why, at the 3rd line, where the flag is created, it is set to false, even before any conditions are tested by the "if" or the "else".
Another detail is the way the distance is handled. In the "if", it is "less than 6 feet". It would be easy to then set the "else" to "more than 6 feet". But that would mean that at exactly 6 feet we are in a never-never land of indecision - a "dead band". To avoid this fate, the "else" was wisely set to "equal or greater than 6 feet".
Thanks to Steven Licciardi, the code guru behind George Lippert's masterful worlds, for coming to my rescue with the above script, when mine had that repeating problem.
The final unfinished biz from my last visit is those cool controls you can script into the "Controls" palette of the Atmosphere plugin. These are easy to copy for your use.
Just copy the control codes from my Audio Lab script, paste them into your own script and change the references to your own. It's a good idea to put the control code right below your code for that individual sound.
Here is an example. You would simply change all the stuff that starts with "my.." to your own names. Don't miss those single quotes on the button label and don't call more than one button by the same name. After you run your script and see how the buttons look, you may want to add spaces (stay inside the quotes) to some button labels to make all your labels line up nicely.
The button names and sound file names must not start with a number or contain spaces or punctuation (except "_" the underscore). Making the first character of each word, after the first word, upper case is a JavaScript programmer's "convention" (an unofficial standard) to make them more readable. Remember that JS is case sensitive, so "myButtonName" is a different name than "mybuttonname".
---------------------------
// - A Typical Sound "Play/Stop" Control -
myButtonName = Button('My Button Label').add();
myButtonName.onClick = function()
{
if (mySound.active)
{
mySound.stop();
}
else
{
mySound.play();
}
}
---------------------------
Next time, I'll attempt to attach a sound to a moving object, so that the sound also moves.
Until then, stay healthy by getting plenty of world building exercise!