Playing Sounds.
Line 26: | Line 26: | ||
''World.Play2DSound()'' plays a non-positional sound, that is it can be heard anywhere | ''World.Play2DSound()'' plays a non-positional sound, that is it can be heard anywhere | ||
on the route. I've added a short pause after the sound is played, enough time to allow the | on the route. I've added a short pause after the sound is played, enough time to allow the | ||
− | sound to play, plus a short pause. On the next loop the | + | sound to play, plus a short pause. On the next loop the method will check to see if the doors |
− | are still open. Once they have closed the ''while'' loop and the method will end. All of this | + | are still open and run again if so. Once they have closed the ''while'' loop and the method |
− | + | will end. All of this runs independently of other parts of the class code. */</font> | |
<font color=blue>thread void RingTheBell(void) { | <font color=blue>thread void RingTheBell(void) { |
Revision as of 12:08, 27 April 2011
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 non-positional sound, that is it can be heard anywhere on the route. I've added a short pause after the sound is played, enough time to allow the sound to play, plus a short pause. On the next loop the method will check to see if the doors are still open and run again if so. 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) { World.Play2DSound(GetAsset(),"bell.wav"); Sleep(1.5); } } /* 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.