intfiction.org

The Interactive Fiction Community Forum
It is currently Mon Nov 20, 2017 8:44 am

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Wed Sep 06, 2017 10:54 am 
Offline

Joined: Tue Jul 28, 2015 1:05 pm
Posts: 979
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:
<audio id="spangled" preload="none" loop>
<source src="the_star_spangled_banner.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>


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.

Code:
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:

Code:
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:

Code:
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
Code:
var MusicOn = false;
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:

Code:
   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:

Code:
   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.


Attachments:
glkote.min.js [205.96 KiB]
Downloaded 10 times

_________________
-My IFDB name is Mathbrush.

Anyone can make interactive fiction; if you've made a game and need a review on IFDB, let me know!
Top
 Profile Send private message  
Reply with quote  
PostPosted: Wed Sep 06, 2017 4:08 pm 
Offline

Joined: Tue Nov 08, 2011 8:11 am
Posts: 2228
Location: US - Central
That's pretty brilliant, and not as scary as one might think.

I wonder how hard it would be for someone to build this into QuixE natively?


Top
 Profile Send private message  
Reply with quote  
PostPosted: Wed Sep 06, 2017 5:42 pm 
Offline

Joined: Fri May 31, 2013 3:54 pm
Posts: 100
Very nice technique, and very nice writeup. Kudos!


Top
 Profile Send private message  
Reply with quote  
PostPosted: Wed Sep 06, 2017 8:32 pm 
Offline

Joined: Fri Oct 18, 2013 10:13 am
Posts: 2467
Location: The Midwest
HanonO wrote:
That's pretty brilliant, and not as scary as one might think.

I wonder how hard it would be for someone to build this into QuixE natively?

The thing with this is that all the sounds are currently hardcoded. For a "native" version you'd want Quixe to load the sounds from the file and have them triggered from the game code directly. Or alternately, use something like Vorple which similarly watches for text printed to a certain channel and reacts accordingly.

_________________
Daniel Stelzer


Top
 Profile Send private message  
Reply with quote  
PostPosted: Wed Sep 06, 2017 8:50 pm 
Offline

Joined: Tue Jul 28, 2015 1:05 pm
Posts: 979
Vorple is my ideal interpreter, but I hate having to set up a fake network to get it to run. As I'm going along, though, I've begun to realize that a lot of cool effects can be achieved from vanilla glulx with just a little tweaking.

For instance, I discovered that you can apply text animations like gas transitions or JavaScript fades to all text that appears, and it takes a very small line of code. It's fun!

_________________
-My IFDB name is Mathbrush.

Anyone can make interactive fiction; if you've made a game and need a review on IFDB, let me know!


Top
 Profile Send private message  
Reply with quote  
PostPosted: Thu Sep 07, 2017 8:06 am 
Offline

Joined: Tue Nov 08, 2011 8:11 am
Posts: 2228
Location: US - Central
I think that's the one thing that holds Vorple back a bit. I would love a standalone interpreter for it, but I'm sure that would be a nightmare to implement across platforms.

It would almost require an extension with lots of "If Vorple is the interpeter.../else..." switches.


Top
 Profile Send private message  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group