エレベータの作成
エレベータを制御しているのは2つのスクリプトです。1つ目のスクリプト「Elevator.lsl」(リスト1)は、エレベータを実際に動かし、アバターとの対話を処理します。2つ目のスクリプト「CallElevator.lsl」(リスト2)は、高層ビルの各階にある緑色のエレベータ呼び出しボタンに適用されます。このスクリプトはメインのエレベータスクリプトと通信し、エレベータを呼び出します。リスト(およびダウンロードサンプル)にはスクリプト全体が含まれていますが、メインのエレベータスクリプトがsit
イベントにどのように反応し、メニューをどのように表示するかが分かるように、スクリプトを順を追って見ていくことにします。
integer CHANNEL = 42; // dialog channel list MENU_MAIN = ["Floor 1", "Floor 2", "Floor 3", "Floor 4", "Floor 5", "Floor 6", "Floor 7"]; // the main menu float BOTTOM = 27.300; float FLOOR_HEIGHT = 10; float SPEED = 1; float target; default { state_entry() { // listen for dialog answers (from multiple users) llListen(CHANNEL, "", NULL_KEY, ""); llSitTarget(<0,-0.5,0.5>, llEuler2Rot(<0,0,-90>) ); llSetText("Sit Here to Ride Elevator",<0,0,0>,1.0); target = BOTTOM; } listen(integer channel, string name, key id, string message) { integer idx = llListFindList(MENU_MAIN, [message]); if( idx!=-1 ) { llSay(0,"Elevator heading to " + message + "." ); target = BOTTOM + (idx*10); state moving; } } changed(integer Change) { llDialog(llAvatarOnSitTarget(), "Where to?", MENU_MAIN, CHANNEL); } } state moving { state_entry() { llSetTimerEvent(0.1); } timer() { vector pos = llGetPos(); pos.x = 50.500; pos.y = 90.740; if( pos.z!=target ) { if( pos.z>target ) { pos.z = pos.z - SPEED; } else { pos.z = pos.z + SPEED; } } if( llFabs(pos.z - target) < SPEED ) { pos.z = target; llSetTimerEvent(0); llSetPos(pos); llSay(0,"Elevator has reached its target." ); state default; } llSetPos(pos); } }
default { state_entry() { llSetText("Touch to Call Elevator",<0,0,0>,1.0); } touch_start(integer total_number) { llShout(42, "Floor 1"); } }
エレベータの構成とセットアップ
エレベータスクリプトの先頭付近に、次のようないくつかの「定数」があります。
integer CHANNEL = 42; // dialog channel list MENU_MAIN = ["Floor 1", "Floor 2", "Floor 3", "Floor 4", "Floor 5", "Floor 6", "Floor 7"]; // the main menu float BOTTOM = 27.300; float FLOOR_HEIGHT = 10; float SPEED = 1;
LSLは定数をサポートしていないので、これらは実際には論理上の定数にすぎません。ここでは高層ビルに合わせた値を指定していますが、これらの定数を変更し、各自のビルに合わせてエレベータを構成することもできます。
CHANNEL
は、エレベータがエレベータ呼び出しボタンと通信するためのチャンネルを定義します。MAIN_MENU
は、各階に対応するボタンを定義します。それと同時に、エレベータの行き先となる階の数も定義します。BOTTOM
は、ビルの1階のZ座標です。SPEED
は、エレベータが移動する速度です。
エレベータをセットアップするために、state_entry
イベントを発生させています。このイベントは、特定の状態に遷移するたびに発生します。リスト1(または下のコード)を見ると分かるように、state_entry
はdefault状態の中に配置されています。default状態はLSLスクリプト起動時の最初の状態なので、このイベントはエレベータが始動すると発生します。システムは、オブジェクトが新しい状態に遷移するたびにstate_entry
イベントを発生させます。すべてのオブジェクトはdefault状態で起動するので、プログラムが起動すると常にdefault状態のstate_entry
イベントが最初に発生します。次にイベントのコードを示します。
state_entry() { // listen for dialog answers (from multiple users) llListen(CHANNEL, "", NULL_KEY, ""); llSitTarget(<0,-0.5,0.5>, llEuler2Rot(<0,0,-90>) ); llSetText("Sit Here to Ride Elevator",<0,0,0>,1.0); target = BOTTOM; }
llListen
コマンドは、指定したチャンネルでリスニングを開始するための指示です。これにより、スクリプトはユーザーがエレベータを呼び出したときにイベントを受け取るようになります。llSitTarget
では、ユーザーがオブジェクトのどこに座ればよいかをx、y、z座標で指定しています。最初のベクトル<0,-0.5,0.5>
は、エレベータの中心を基準とする位置を指定します。2番目のベクトル<0,0,-90>
は、オブジェクトに対してユーザーのアバターをどのように回転させるかを指定します。この場合、アバターはz軸を中心に-90度回転します。z軸とは上下に延びる軸のことです。従って、z軸を中心に回転すると、アバターは地面に足を付けたままで、対面している方向を変えます。z軸は、頭の上から足の下まで延びている架空の直線と考えることができます。さらに、llSitTarget
を呼び出すことで、ユーザーがオブジェクトに座ったときにオブジェクトがイベントを受け取れるようにしています。
llSetText
メソッドは、オブジェクトの上部に説明文を表示します。この例では、エレベータに乗るには座る必要があることをユーザーに知らせます。最後に、エレベータの行き先のz座標(target
変数に格納される)をBOTTOM
、つまり1階に初期化しています。