Automating Animations.

From TrainzOnline
(Difference between revisions)
Jump to: navigation, search
m (1 revision)
m
Line 68: Line 68:
 
The selected train should head off towards the engine shed. Once it gets close enough the doors should open and the train should slow down as it approaches the end of the track. Once inside the train should stop and the doors should close. Since the shed doesn't currently have a visible roof you will be able to see all of this happening.
 
The selected train should head off towards the engine shed. Once it gets close enough the doors should open and the train should slow down as it approaches the end of the track. Once inside the train should stop and the doors should close. Since the shed doesn't currently have a visible roof you will be able to see all of this happening.
  
If its not quite right you may need to go back to the gmax source and adjust some of the dimensions.  The Object messages which control the doors are issued when the centre point of the traincar crosses the trigger radius.<br><br>
+
If its not quite right you may need to go back to the Max source and adjust some of the dimensions.  The Object messages which control the doors are issued when the centre point of the traincar crosses the trigger radius.<br><br>
 
Next Tutorial: [[Handling Corona Effects.]]<br>
 
Next Tutorial: [[Handling Corona Effects.]]<br>

Revision as of 19:34, 25 March 2010

The code to deal with this follows. Any text sandwiched between /* and */ character pairs, and the text on any line starting with //, will be treated as a comment and ignored by the compiler.

include "Buildable.gs"

class Tutorial isclass Buildable {

/* We will need a variable to keep track of whether the shed doors are open or closed,
   declaring this in the body of the class and outside of any method definitions will
   make it available to any method in the class.*/ 

   bool doorsOpen = false;

/* We are going to open and close the doors whenever a vehicle enters or leaves the area 
   defined by our trigger.  To do this we will be listening for Object,InnerEnter and
   Object,InnerLeave messages. We do this by adding a handler in Init().*/ 

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

/* Object handler will 'wake up' whenever we receive an Object message. It is good 
   practice to check that the message is coming from an expected source. This is done 
   by converting or 'casting' the source of the message to a vehicle.  If the cast does
   not work the variable vehicle will be null and the handler is exited immediately. 
   The remainder of the method checks whether the vehicle is entering or leaving and runs 
   the animations as appropriate. SetMeshAnimationState() runs the animation attached 
   to the named mesh from its current position to the beginning or end, depending on the 
   value of the second parameter.*/ 

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

};

There are a couple of quirks to notice about the code in ObjectHandler:

1. The cast statement Vehicle vehicle = cast<Vehicle>msg.src;

  • If you have remembered that TrainzScript is case sensitive you will see that there is a difference between Vehicle and vehicle.
  • The former is a built-in class name and the latter is a variable, so the phrase Vehicle vehicle is a declaration of a variable called vehicle to be of the class Vehicle. You may need to read that a couple of times.
  • I don't personally like this convention (script is confusing enough without it) but you will see it frequently so you might as well start getting used to it now.

2. The if statement if (msg.minor == "InnerEnter") doorsOpen = true;

  • == and = mean different things.
  • doorsOpen = true is an assignment, the same as saying let doorsOpen be equal to true.
  • msg.minor == "InnerEnter" is a comparison which will return true if msg.minor is equal to "InnerEnter" and false otherwise.
  • The most common mistake you will make is to type if (msg.minor = "InnerEnter"), missing out the second equals sign. This will always evaluate to true, will usually mess up your code, and will always be difficult to spot. You have been warned.


To check out your script:

  • Compile the code and reload and commit the asset.
  • Start Surveyor and place an instance (a copy) of the object on your map.
  • Add a section of track to the track node nearest to the doors and extend it some distance away from the object
  • Place a railcar or something similar at the far end of the track, orient it towards the engine shed.
  • Go to Driver via the Quick Launch button, select DCC mode and click on the train that you have just placed.
  • Issue a Drive command.

The selected train should head off towards the engine shed. Once it gets close enough the doors should open and the train should slow down as it approaches the end of the track. Once inside the train should stop and the doors should close. Since the shed doesn't currently have a visible roof you will be able to see all of this happening.

If its not quite right you may need to go back to the Max source and adjust some of the dimensions. The Object messages which control the doors are issued when the centre point of the traincar crosses the trigger radius.

Next Tutorial: Handling Corona Effects.

Personal tools