Saturday, 10 August 2013

a java-script game: a Sound-Library and type-checking

Sound is essential in video games.  Luckily, sound is realy easy in java-script.  There is a thing called the Audio object.  Much the same as the Image object.  We can create an almost identical library to the image library we created before to play sounds in our game.

Here is little sample that'll play a sound when the page is loaded.  The sound load synchronously, as opposed to images that insist on loading asynchronously.  Making our job a little easier.

<html>
<body>

<script type="text/javascript">
<!--
  // create the object
  var sound1 = new Audio();
  // set the location of the sound
  sound1.src = "http://peter3125.freewebhost.co.nz/snd/drop.mp3";
  // if the object has the methods we expect it to have,
  // load it and play it
  if ( sound1.load && sound1.play )
  {
    sound1.load();
    sound1.play();
  }

//-->
</script>

</body>
</html>


Notice the if statement above.  Its actually not needed from a programmatic point of view.  It is an issue of style.  The "if" statement checks for the existence of a "load" and a "play" method on the sound1 instance of the Audio() object.  Strictly speaking the "if" statment isn't quite there yet.

Perhaps its time to quickly mention some of the java-script operators.  In a typical programming language like C# / C / C++ there are several operators you can use to compare things.

Typically in Java and C# you'd want to use a statement like

if ( obj != null ) ...

which reads "if object is not null", meaning "if the object exists" pragmatically.  "!=" is the "does not equal" operator.

similarly if we wanted to make sure an object didn't exist we'd write

if ( obj == null ) ...

where "==" is the equals operator (aka. the double equals operator).

Java-script's == operator is a little cleverer than the C# / Java operator of the same name.  Java-script's == operator will try and convert types to make them match.  In java-script

if ( "5" == 5 )
{
   alert("they're equal!");
}

will show a dialog box, in Java and C#, not so much.

If you want to use the equivalent operator to C# and Java there is the === (triple equals) operator.  That operator compares the values without doing any conversion.

if you want to check that something has been defined, you'd use

if ( typeof(myvar) === 'undefined' ) alert("myvar is not defined");

if you wanted to check if something is an existing function on an object you'd write:

var myAudio = new Audio();
if ( typeof(myAudio.play) === 'function' ) alert("myAudio.play is a function");

the "if" statements I used above are lazy versions of the same.  They basically read "if sound1 has something called play that isn't undefined".  That isn't strictly speaking the same as checking whether it is a function or not.  And since I then try to use it as a function.  You can already figure out that this shortcut could end up trying to use a "property" called "play" on the object as a function.  That would fail.  BUT, since Audio() is one of those well defined functions provided to you by java-script, you can (for now, until they change the standard) rely on the fact that if it has something called "play" on it, that play will be a "function".

So then you say: "well, so why do you check for it at all?".  Good point.  Best answer is "habit".  And its a good habit to have and to start using.  My rule is to always check for "null" in languages such as Java and C#.  If you do write those few extra lines, right from the start, you will always end up with better code (and more code, but thats not a plus necessarily).

So we might as well dig straight into a little sound library class.  I'll just take the image library we created before, and refactor it a little to deal with sounds.

<html>
<body>

<script type="text/javascript">
<!--
 
  // little sound library
  function AudioLibrary()
  {
    var self = this;
    var lookup = {};

    // no callback methods needed - just setup the sounds
    this.setup = function( callback )
    {
      // just to make this sampel work using my free website
      // remove base here and below to make it work for your own stuff
      var base = "http://peter3125.freewebhost.co.nz/";
      this.load( "fire-missile", base + "snd/drop.mp3");
      this.load( "land-ship", base + "snd/land.mp3");
      this.load( "explode", base + "snd/explosion.mp3");
      this.load( "shoot", base + "snd/shot.mp3");
    };

    // setup a loader with a wait function
    this.load = function( str, src )
    {
      var sound = new Audio();
      sound.src = src;
      if ( sound.load )
      {
        sound.load();
      }
      lookup[str] = sound;
    };

    this.play = function( str )
    {
      if ( lookup[str] && lookup[str].play )
      {
        lookup[str].play();
      }
    };

  }
 
  // the the library
  // create a new instance
  var sndLib = new AudioLibrary();
  // load all the sounds
  sndLib.setup();
  // play two sounds - pretty much at the same time
  sndLib.play( "fire-missile" );
  sndLib.play( "explode" );
 
 
//-->
</script>

</body>
</html>

No comments:

Post a Comment