メニューの表示
ユーザーがエレベータに座ると、Second Lifeはエレベータスクリプトにchanged
イベントを送ります。イベントハンドラのコードは次のようになっています。
changed(integer Change)
{
llDialog(llAvatarOnSitTarget(), "Where to?",
MENU_MAIN, CHANNEL);
}
llDialog
メソッドは、ユーザーに簡単なメニューを表示します。
ユーザーが行き先の階を選択すると、次のlisten
イベントが発生します。
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; } }
listen
イベントが発生すると、message
イベントパラメータにユーザーが選択したメニュー項目のテキストが格納されます。listen
イベントはまず、MAIN_MENU
配列で選択された要素のインデックスを確認し、整数変数idx
の値を、ユーザーが選択した階の0で始まるインデックスに設定します。次に、エレベータはその階に向かっていることを報告し、target
変数を設定します。最後に、状態をmovingに変更します。
複数のアバターが一度にエレベータに座る可能性もあります。この場合は、行き先の階を選ぶポップアップがアバター全員に表示されます。このエレベータは、現実のエレベータのように階を「待ち行列に入れる」ことはしません。代わりに、最後のアバターが選択した階がエレベータの行き先になり、すべてのアバターがこれに相乗りします。
オブジェクトの移動
Second Lifeでオブジェクトを動かすには2種類の方法があります。オブジェクトを押して物理的に動かす方法と、x、y、z座標を使って直接動かす方法です。オブジェクトを直接動かす方が物理的に動かすよりもいくぶん簡単なので、ここでは座標ベースの移動を中心に説明します。幸い、エレベータは上下に1次元の動きしかしないので、座標ベースの移動はかなり単純です。ご想像どおり、Second Lifeでは、これはz座標になります。
エレベータはmoving状態に遷移すると動き始めます。moving状態が始まると、state_entry
イベントが発生します。
state moving { state_entry() { llSetTimerEvent(0.1); } : : :
state_entry
イベントは、毎秒10回ずつ時を刻むタイマーを登録します。タイマーが時を刻むごとにtimer
イベントが発生します。するとtimer
イベントのコードがエレベータを動かします。timer
イベントは、まず次のようにエレベータの現在位置を取得します。
timer() { vector pos = llGetPos(); : : :
指定された行き先とz座標が一致しない場合、スクリプトは行き先に向かって上または下にエレベータを動かします。SPEED
定数は、エレベータが行き先に到達する速度を制御します。
if( pos.z!=target ) { if( pos.z>target ) { pos.z = pos.z - SPEED; } else { pos.z = pos.z + SPEED; } }
エレベータの現在位置が行き先間近になる(SPEED
定数に指定された距離より短くなる)までは、タイマーが時を刻むたびにこれが繰り返されます。現在位置が行き先間近になると、スクリプトはエレベータを行き先の正確な位置まで移動し、タイマーを停止し、ユーザーに通知し、エレベータの状態をdefault状態に戻します。
if( llFabs(pos.z - target) < SPEED ) { pos.z = target; llSetTimerEvent(0); llSetPos(pos); llSay(0,"Elevator has reached its target." ); state default; }
まだ行き先間近になっていない場合はエレベータを動かし続ける必要があるので、タイマースクリプトは計算された新しい位置にエレベータを移動します。
llSetPos(pos);
ユーザーがエレベータに座って制御する以外に、緑色のエレベータ呼び出しボタンを使って特定の階にエレベータを呼び出すこともできます。これを行うには、オブジェクト間の通信が必要になります。
オブジェクト間の通信
Second Lifeのオブジェクトは、アバター同士が会話するのとほぼ同じ方法で相互に通信します。アバターは、近くにいるアバターに聞こえるように何かを「言う」(Say)ことができます。また、遠くに聞こえるように「叫ぶ」(Shout)こともできます。Second Lifeの通信は、すべて特定のチャンネルを通じて行われます。アバターは通常、チャンネル0を使って会話します。オブジェクトがチャンネル0でリスンしていれば、そのオブジェクトは近くにいるユーザーの話を聞くことができます。同様に、オブジェクトがチャンネル0で発言すれば、近くにいるユーザーはそれを聞くことができます。
高層ビルの各階には、エレベータを呼び出す緑色のボタンがあります。このボタンの仕組みはごく単純で、単にどの階でエレベータを呼び出しているかを伝えているだけです。これをエレベータのメニューとまったく同じ方法で行っています。
各階のボタンにはtouch_start
イベントが含まれており、ユーザーがボタンに触れるとイベントが発生します。次に示すのは、1階のボタンのtouch_start
イベントです。
touch_start(integer total_number)
{
llShout(CHANNEL, "Floor 1");
}
このスクリプトではメッセージを叫んで(Shout)います。高層ビルは非常に高い場合があるので、llSay
メソッドよりも遠くまでメッセージを届ける必要があるからです。エレベータはlisten
イベントでこのメッセージを受信し、指定された階への移動を開始します。
本稿では、Second Lifeでエレベータを作成する方法を紹介しました。これはほんの入り口にすぎません。LSLライブラリの数々のメソッドを使うと、ゲーム内のオブジェクトをほぼ無限に作り出すことができます。商取引を行って他のオブジェクトを販売するためのオブジェクトを作成したり、Second Life内のゲームで使う武器を作成したりできます。また、オブジェクトで外部のWebサーバとやり取りし、スクリプトで外部リソースを利用することもできます。
LSLについてさらに詳しく知りたければ、Linden Labs社が運用するLSLプログラミングに関するWikiで詳細な情報を得ることができます。