Playing Sounds.

From TrainzOnline
(Difference between revisions)
Jump to: navigation, search
 
m (1 revision)

Revision as of 23:59, 3 February 2010

Trainz is capable of doing quite sophisticated tricks with sound files. We will use a file which contains a single 'ding' but loops it around continuously as long as the doors to the shed are open. This involves the use of a separate programming thread. A thread runs independently of any other code within your script. It's a bit like leaving the kettle boiling while you answer the front door, the kettle will look after itself until it boils. In the same way our thread will look after itself until something tells it to stop.

include "Buildable.gs"

class Tutorial isclass Buildable {

   bool doorsOpen = false;

   public void Init(void) {
      inherited();
      SetFXCoronaTexture("corona",null);
      AddHandler(me,"Object","","ObjectHandler");
   }

   Asset GetCorona(string mesh, string effect) {
      Soup meshtable = GetAsset().GetConfigSoup().GetNamedSoup("mesh-table");
      Soup effects = meshtable.GetNamedSoup(mesh).GetNamedSoup("effects");
      KUID kuid = effects.GetNamedSoup(effect).GetNamedTagAsKUID("texture-kuid");
      return World.FindAsset(kuid);
   }

/* This is the bell ringing method, the keyword thread signifies that it is to run
   independently of any other code.  You will remember our global variable, doorsOpen
   which is set to true or false in the ObjectHandler method. RingTheBell uses a while
   loop to monitor this variable and will keep running until doorsOpen becomes false.
   World.Play2DSound() plays a sound file and returns the length of the file in seconds. 
   I've added a short pause to this and the overall result is that the method waits until 
   the file has played, waits a short while longer, and then goes back to the beginning to 
   see if the doors are still open. Once they have closed the while loop and the method 
   will end. All of this runs independently of other parts of the class code. */

   thread void RingTheBell(void) {
      while (doorsOpen) {
         Sleep(0.35 + World.Play2DSound(GetAsset(),"bell.wav"));
      }
   }

/* When the doors are opened we call the thread RingTheBell to start the bell ringing.
   There is no need to stop it, this will happen automatically. */

   void ObjectHandler(Message msg) {
      Vehicle vehicle = cast<Vehicle>msg.src;
      if (!vehicle) return;
      if (msg.minor == "InnerEnter") {
         doorsOpen = true;
         SetMeshAnimationState("default", true);
         SetFXCoronaTexture("corona",GetCorona("default","corona"));
         RingTheBell();
      }
      else if (msg.minor == "InnerLeave") {
         doorsOpen = false;
         SetMeshAnimationState("default", false);
         SetFXCoronaTexture("corona",null);
      }
   }

};

I've used World.Play2DSound() to ring the bell because you will hear it no matter how far away from the shed the camera is zoomed. It would actually be more appropriate to use a different method, World.PlaySound() which will appear to come from one speaker or the other, depending on where you are, and will fall off in volume as you get further away from the building. The call for this would be World.PlaySound(me,"bell.wav",1000,10,100,me,"a.corona"); You might like to try a substitution to hear the difference.

Next Tutorial: Hiding Meshes.

Personal tools