I found an easy way to add music to Quixe based on your location for my IFComp game, and I thought I’d write a tutorial for it, since it’s so easy and I don’t just want to hide it. This could all be much more concise if it were function-ified, but one characteristic of this forum is that when someone posts code, someone posts better code, which would be great in this situation.
You’ll need some kind of text editor to edit html and js files (I used Notepad++ in Windows). I’ve added a sample glkote.min.js file to show what the completed setup is like.
Step 1
Make sure you have a glulx file and that you ‘release with an interpreter’. This modification only works if you haven’t modified the status line.
Step 2
Add the music files you want to your materials directory (the same one that has play.html). There are many music formats that could work with this technique, but mp3’s play on the most browsers. (They used to require a licensing fee, but that expired this year).
Step 3
Open up play.html. Copy and past the following to add a song to the list of playable music:
[code]
Your browser does not support the audio element. [/code]I placed this right before the /body tag at the end. The ‘preload = “none”’ is designed to make the game load faster, and the word ‘loop’ tells the website to loop the audio. The ‘id = “spangled”’ is just a place to name the audio you’ve added, so you can refer to it later.
Step 4
In the Interpreter folder of the Materials folder, open up glkote.min.js.
Search this document for the phrase ‘insert_text_detecting(el, rtext);’. It should appear three times. The first time represents the status line; the second time represents all other text; and the third one is where that function is actually defined.
The first time that it occurs, we replace that line with our music system. This part is complicated, so I wanted to show how I built it up. I initially just detected what room you’re in. The if statement detects the room name (slice just gets the first few characters, and the == tells if it is equal to whatever room you’re looking for. The slice starts at 1 because the status line always has a space in it; it ends at 1+the number of letters in the room name). In the ‘getelementbyID’ parentheses you just put the name that you gave the music earlier.
if(rtext.slice(1,11) == 'First Room'){
document.getElementById('spangled').play();
}
else if(rtext.slice(1,5) == 'Home'){
document.getElementById('spooky').play();
}
insert_text_detecting(el, rtext);
However, this won’t turn off the old audio when the new audio starts playing. What I did with this was I paused all of the other music and then set their times to 0 (the most common way of ‘stopping’ music in HTML5). So now it looks like this:
if(rtext.slice(1,11) == 'First Room'){
document.getElementById('spooky').pause();
document.getElementById('spooky').currentTime = 0;
document.getElementById('spangled').play();
}
else if(rtext.slice(1,5) == 'Home'){
document.getElementById('spangled').pause();
document.getElementById('spangled').currentTime = 0;
document.getElementById('spooky').play();
}
insert_text_detecting(el, rtext);
However, this causes an error in Internet Explorer where you can’t set currentTime if the song is not currently loaded. This was hard to work around; I had to google around a lot. Basically, you just check to see if you can even access the song, and if you can, then you set currentTime to 0:
if(rtext.slice(1,11) == 'First Room'){
document.getElementById('spooky').pause();
if(document.getElementById('spooky').readyState > HTMLMediaElement.HAVE_NOTHING){
document.getElementById('spooky').currentTime = 0;
}
document.getElementById('spangled').play();
}
else if(rtext.slice(1,5) == 'Home'){
document.getElementById('spangled').pause();
if(document.getElementById('spangled').readyState > HTMLMediaElement.HAVE_NOTHING){
document.getElementById('spangled').currentTime = 0;
}
document.getElementById('spooky').play();
}
insert_text_detecting(el, rtext);
This is the final code that I used, and it works in every browser I tried (including safari, chrome, firefox, internet explorer, android, and iOS).
Step 5
You may want to be able to turn music on and off. In that case, you can open glkote.min.js again. At the top, there are a bunch of statements starting with ‘var’ and ending with semicolons; in the middle of these, add the phrase
var MusicOn = false;
[/code] to add a global variable that turns music on and off.
Then you can add code like the following to your Inform game:
[code]To turn on the music:
say "Music has been enabled. Press any key.";
now the left hand status line is "Music Enabled";
update the status line;
wait for any key;
now the left hand status line is "[the player's surroundings]";
now MusicOn is 1;
And add the following line next to all your other ‘if’ statements in glkote.min.js:
if(rtext.slice(1,14) == 'Music Enabled'){
MusicOn = true;
}
Then you can take all of your ‘if’ statements and wrap them in one big if statement:
if(MusicOn == true){
.....code goes here
}
You can do similar things to turn the music off in-game (making sure to stop all music running).
Summary
Except for that last little bit about turning music off and on, this is all done completely in-browser, without changing the game file, which means that the game file will work just fine when played offline (the music will just not play). Because the status line is redrawn after UNDO/RESTART/RESTORE, the music plays just fine after these events.
glkote.min.js (206 KB)