The Caledon Tram is now complete. Well, it is at least running, trundling the streets of Caledon, Caledon II and Port Caledon and occasionally stopping and tinging a little bell for folk to jump onto it. It is also operating, it seems, reliably, which is really rather important for public transport and something that I wish would be more appreciated by Transport Ministries in the Other World.~ * ~
It has taken me some time to script this device, which perhaps it should not have, given its relative simplicity. The core of the tram is the same notecard reader which powers my balloons (the Touring Dirigible is still at the Lighthouse, incidentally) but the movement is, this time, nonphysical, as I believe I have mentioned before.
I recently discovered that there are people unaware of the difference, so, a quick description: physical movement involves physical objects, which must pass through intervening space, may collide with other objects, bounce off them, twist through the air and so on. One can set the physics flag on an object quite simply from the "edit" menu, and then grab said object and throw it about if you so desire, or use scripting functions to apply forces to it. Physical Non-physical movement involves nonphysical objects, like the majority of the scenery that you see around you in Second Life. These can be repositioned using the function
llSetPos, and rotated with
llSetRot. They do not react to the presence of other objects unless scripted to, which explains why, if one stands in front of the moving tram, one is not actually flattened by it but instead startled as it passes right through one's body.
The tram's linear motor is really a timer that triggers a number of subscripts via linked message, each one calling
llSetPos to move it a tiny distance ahead, so that the overall effect is of relatively smooth movement... this is not actually as smooth as physical movement but in practice, not so bad. One peculiar quirk of nonphysical vehicles seems to be that, if someone is actually controlling them directly, they traverse SL in a manner far more smooth than if they are without a controlling avatar... however we do not really have the option of a permanent tram driver (perhaps, a profession for new residents in the future?)
The instructional notecard mostly contains a series of waypoints between which the tram moves, and its behaviour is predictable upon reaching each one:
1. read for the next waypoint;
2. find out its direction relative to the current position;
3. turn on the spot to face that direction;
4. repeatedly move forward a small fraction of that directional vector until reaching it.
The turning part gave me an appalling headache and the process exemplifies, I think, the simple principle "don't believe anything you tell yourself". The sub-process of turning can be laid out as follows:
1. which direction am I facing in now? (
2. which direction should I be facing in? (
llVecNorm(targetPos - llGetPos()));
3. what is the angle between these two directions? (
4. if this angle is not within one turning increment, repeatedly rotate around the Z-axis by that increment in a suitable direction until it is;
5. do one final rotation to face the target.
Now, clearly if the destination is clockwise of the actual facing of the tram, one should turn clockwise, and similarly for anticlockwise, or the tram will spin around far too much and look daft. However, and here is the embarrassing bit, I had become convinced for some unknown reason that
llAngleBetween would return a value greater than
PI if one vector was to the left of the other. I have absolutely no idea how I decided that this was the case since it isn't, but I had taken that as one of my hypotheses and did not question it for ages, with the result that the tram rotated on the spot in an annoying fashion with me shouting "ARGH WHY ARE YOU DOING THIS YOU STUPID THING" when in fact it was I who was the stupid one. Let this be a lesson to you, dear reader - we are all idiots, particularly me.
The tram, however, regardless of script untidiness and possible improvements, is now running, and people have told me that they enjoy riding it and find it a most pleasant addition to Caledon and that makes it all worthwhile. (I have been invited to possibly develop a similar system for Second Life's Third Birthday Celebrations, so it may reach a wider audience.)
Whilst I did script the tram, the actual building and texturing work was done by those master craftsmen Reitsuki Kojima and Shaunathan Sprocket, and it is they who one needs to thank for its elegant two-wheeled steam-powered design. Scripts are nothing without an actual tram to put them in and those gentlemen deserve the lion's share of praise. If it were left up to me doubtless the trolley would be a box with rivets on it, and nobody would think it pleasant to ride at all.
~ * ~
Those of you hoping for a view of my Stretched Metaphor may have to wait for a little while, as I have become distracted, but I can tell you that it involved eggs.