Twine Version: 2.11.1
Sugarcube 2.37.3
Hi there! I couldn’t find this particular issue on here. I hope this is an original problem!
I’m making a story where I want audio to play in exterior spaces, but to fade out when the player moves to an interior space. The audio in question does not loop; it has a distinct ending. Currently I’ve got this code in my exterior passages:
<<if $BWtheme is true>>\
<<else>>\
<<audio "BWtheme" fadeoverto 1 1>>\
<<set $BWtheme to true>>\
<</if>>\
…and this code in my interior passages:
<<if $BWtheme is true>>\
<<audio "BWtheme" fadeoverto 1 0>>\
<<set $BWtheme to false>>\
<</if>>\
This mostly works fine. Basically, if the audio is already playing it continues playing while the player moves between exterior passages, and it fades quickly once they move to an interior passage. Then, once they move back to an exterior passage, the audio fades back in at the point where it left off.
The problem arises once the audio file ends. The way I’ve coded this now, when the audio file stops playing, the $BWtheme variable remains “true”, so that when the player moves to an interior passage, the audio macro with the fadeoverto action is triggered - which results in a rather disruptive one-second snippet of the audio playing from the start and immediately fading.
I wonder if there is a way that I could set the $BWtheme variable to “false” at the moment when the audio stops playing? Or if there is another way to do this that I’m overlooking? (One solution would be to simply loop the audio so that it is always playing when the player moves to an interior passage. But I’m not sure I want to do this.)
Thanks for your help!
I should clarify that in this case the audio begins playing before the first instance of the code I’ve cited here, which is why it works at all. Maybe that’s obvious, just figured I’d clear that up.
First, a couple of general things:
1: There is no need for the is comparison operator when evaluating a Boolean variable.
/* no operator is needed to check for Boolean true */
<<if $BWtheme>>processed if BWtheme variable equals true<</if>>
/* a negate operator is needed to check for Boolean false, SugarCube has two... */
<<if not $BWtheme>>processed if BWtheme variable equals false<</if>>
or
<<if ! $BWtheme>>processed if BWtheme variable equals false<</if>>
2: There should never be a need to have an empty body when using an <<if>> + <<else>> structure…
<<if $BWtheme>> /* do nothing when the variable equals true */
<<else>>
<<audio "BWtheme" fadeoverto 1 1>>
<<set $BWtheme to true>>
<</if>>
…instead you should check for the reverse or opposite of the condition…
<<if not $BWtheme>>
<<audio "BWtheme" fadeoverto 1 1>>
<<set $BWtheme to true>>
<</if>>
SugarCube’s Audio related API allows checking is a track is currently playing. The SimpleAudio.tracks.get() method can be used to gain access to the track’s definition, and the <AudioTrack>.isPlaying() method can be used to determine if that track is playing.
Combining those two methods together in a Passage would looks something like…
/* check if the track is playing, and continue playing it if it is... */
<<if SimpleAudio.tracks.get("BWtheme").isPlaying()>>
<<audio "BWtheme" fadeoverto 1 1>>
<</if>>
/* check if the track is playing, and stop it if it is... */
<<if SimpleAudio.tracks.get("BWtheme").isPlaying()>>
<<audio "BWtheme" fadeoverto 1 0>>
<</if>>
note: I’m unsure if setting the fadeoverto of a playing track to 1 is the best way to continue playing the track.
2 Likes
Hey, this is enormously helpful. I’ll give the SimpleAudio.tracks.get() and<AudioTrack>.isPlaying() combined methods a try later today. Thanks for your general comments as well; I’ll be able to clean up my story a fair bit, keeping this in mind.
Thanks for taking the time!