|
任天堂が、大画面の「ニンテンドーDSi LL」を発表。欲しいと思いますか?
|
リンデンスクリプトを使ったSecond LifeのプログラミングはじめにSecond Life(SL)は、Linden Labs社が制作した大人気の多人数同時参加型オンラインゲーム(MMOG)です。Second Lifeはゲームをはるかに超えるものだと考える人も大勢います。Second Lifeをよく知らない人は、映画『マトリックス』を思い出してください。『マトリックス』では、人々がシミュレーションの世界の中で生活し、仕事をしていました。Second Lifeもこれとそっくりで、アバターと呼ばれるコンピュータプレーヤーがSecond Lifeの3Dの世界の中で生活します。 Second Lifeに明確な目的はありません。この世界で起きることはすべて、プレーヤーの自由な発想に任されています。しかも、Second Lifeは無料でプレーすることができます。登録する必要はありますが、土地を所有するのでなければ有料会員になる必要はありません。 ただし『マトリックス』と違い、現在のコンピュータ技術は現実の世界を丸ごとシミュレートできるほど進歩していません。そのため、Second Lifeには2つの大きな短所があります。第一に、プレーヤーはコンピュータの画面を通してSecond Lifeの世界を目にします。最先端の3Dグラフィックスが使われているとはいえ、シミュレーションはどことなく漫画チックに見えます。それでも、Second Life内ではかなり水準の高いビジュアル表現が随所に見られます。 第二に、Second Lifeのシミュレーションは物理的に完全なシミュレーションではありません。重要な要素、例えば重力などは存在しますが、車のような複雑なものは完全にシミュレートできないことがあります。車の内燃機関や電気部品のすべての側面をシミュレートするのはかなり難しいことだからです。最新のコンピュータであっても、このような処理にはパワーが足りません。とはいえ、これから見ていくように、Second Lifeの世界には車やその他多くの種類の乗り物が存在します。 Second Lifeにアクセスするには、無料のクライアントを使用します。クライアントはWindows、Macintosh、UNIXなど、各種のOSに対応しています。さらに、Linden Labs社はつい先日、クライアントをオープンソースとして公開しました。これにより、サードパーティの開発者がSecond Lifeクライアントのさまざまな追加機能を作成し、機能を拡張できるようになっています。 Linden Scripting LanguageについてSecond Lifeには、単純な物理エンジンの機能の限界をフォローするために、Linden Scripting Language(以下LSL)というスクリプト型のプログラミング言語が用意されています。車のすべての側面をシミュレートする代わりに、車の動き方を指示するスクリプトをプログラマが作成します。このスクリプトでは、音を鳴らすことも、車の進路を変えることも、衝突を検出することもできます。例えば車のスクリプトを作成する場合、現実味を加えるために、運転中でなければ進路を変更できないようにすることもできます。 本稿ではLSLの概要を紹介します。ここで説明する内容を十分に活用するには、Second Lifeにおける「制作」(building)の基礎知識があることが望ましいものの、それは本稿のコードを理解する上で必須ではありません。制作とは、3Dプリミティブ(基本形状)をSecond Lifeの世界に配置する作業です。Second Lifeで目にするものはすべて、制作者によって作成されています。 本稿では、読者が既にSecond Lifeの制作工程にある程度精通しているという前提で話を進めます。Second Lifeで簡単なオブジェクトを制作するのはそれほど難しいことではありませんが、物を制作するにはSecond Lifeの世界のやり方を学ぶ必要があります。試しに制作してみるには、Second Lifeウィンドウの下にある[Build]ボタンをクリックします。 LSLの基礎 LSLは、一見するとCによく似ています。しかし、プログラミングはCよりもずっと簡単です。ポインタはなく、 LSLスクリプトは、Second Lifeの3Dプリミティブの中に配置されます。オブジェクトはプリミティブの集合です。例えば、Second Lifeの車は1つのオブジェクトです。しかし、車オブジェクトは、それぞれが独自のスクリプトを含む多くのプリミティブで構成されます。また、プリミティブは相互に、あるいは人間のプレーヤーと通信することができます。高度なプログラミングを使うと、プリミティブはSLの外部にあるWebページとも通信できるようになります。 LSLはイベントドリブンでもあります。Second Lifeのほとんどのオブジェクトは、イベントをきっかけに状態を遷移しながら機能します。Second Lifeには、さまざまな種類のイベントが用意されています。その多くはユーザーがオブジェクトに触れたり座ったりしたときに発生するユーザーベースのイベントですが、ユーザーの操作が不要なタイマーイベントもサポートされています。 これ以降は、Second Lifeでエレベータを動かす方法について説明します。 簡単なエレベータの制作例として、本稿ではSecond Lifeの高層ビルを上下に移動するエレベータを作成する方法を示します。図1は、このエレベータを設置する高層ビルです。 このエレベータが実際に動作する様子は、Second LifeのX座標51、Y座標79の位置にある「Gyeonu」リージョンで確認できます。Second Lifeでは、「SLURL」と呼ばれる特殊なURLが使われます。SLクライアントが既にインストールされていれば、エレベータの場所に直接移動することができます。SLURLリンクがうまく機能しない場合は、SLクライアントの[Map]ボタンをクリックして「Gyeonu」を検索し、座標フィールドに「95」、「23」、「44」という座標を入力します(※編集部注:現在、該当する座標に高層ビルのオブジェクトは設置されていないようです)。 このリンクをたどると、エレベータがあるエリアの上空マップを示すWebサイトが開きます。Second Lifeがインストールされている場合は、[Teleport Now]をクリックしてその場所にテレポートすることができます。エレベータを使うと、屋上を含めて、高層ビルのすべての階に移動できます。エレベータを利用するには、単にエレベータに「座る」(sit)という動作を行います。これは組み込みの動作の1つで、ゲーム内のオブジェクトを右クリックするとポップアップメニューに表示されます。エレベータのポップアップメニューでは、行き先の階を選択することができます。また、高層ビルの各階にある緑色のボタンを使うと、エレベータをその階に呼ぶことができます。 エレベータの作成 エレベータを制御しているのは2つのスクリプトです。1つ目のスクリプト「Elevator.lsl」(リスト1)は、エレベータを実際に動かし、アバターとの対話を処理します。2つ目のスクリプト「CallElevator.lsl」(リスト2)は、高層ビルの各階にある緑色のエレベータ呼び出しボタンに適用されます。このスクリプトはメインのエレベータスクリプトと通信し、エレベータを呼び出します。リスト(および[ダウンロードサンプル[#dl])にはスクリプト全体が含まれていますが、メインのエレベータスクリプトが リスト1 Elevator.lslスクリプト
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); } } リスト2 CallElevator.lslスクリプト(超高層ビルの各階にある緑色の呼び出しボタンでエレベータを呼び出す)
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は定数をサポートしていないので、これらは実際には論理上の定数にすぎません。ここでは高層ビルに合わせた値を指定していますが、これらの定数を変更し、各自のビルに合わせてエレベータを構成することもできます。 エレベータをセットアップするために、
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;
}
メニューの表示 ユーザーがエレベータに座ると、Second Lifeはエレベータスクリプトに
changed(integer Change)
{
llDialog(llAvatarOnSitTarget(), "Where to?",
MENU_MAIN, CHANNEL);
}
ユーザーが行き先の階を選択すると、次の
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;
}
}
複数のアバターが一度にエレベータに座る可能性もあります。この場合は、行き先の階を選ぶポップアップがアバター全員に表示されます。このエレベータは、現実のエレベータのように階を「待ち行列に入れる」ことはしません。代わりに、最後のアバターが選択した階がエレベータの行き先になり、すべてのアバターがこれに相乗りします。 オブジェクトの移動Second Lifeでオブジェクトを動かすには2種類の方法があります。オブジェクトを押して物理的に動かす方法と、x、y、z座標を使って直接動かす方法です。オブジェクトを直接動かす方が物理的に動かすよりもいくぶん簡単なので、ここでは座標ベースの移動を中心に説明します。幸い、エレベータは上下に1次元の動きしかしないので、座標ベースの移動はかなり単純です。ご想像どおり、Second Lifeでは、これはz座標になります。 エレベータはmoving状態に遷移すると動き始めます。moving状態が始まると、
state moving
{
state_entry()
{
llSetTimerEvent(0.1);
}
:
:
:
timer()
{
vector pos = llGetPos();
:
:
:
指定された行き先とz座標が一致しない場合、スクリプトは行き先に向かって上または下にエレベータを動かします。 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); ユーザーがエレベータに座って制御する以外に、緑色のエレベータ呼び出しボタンを使って特定の階にエレベータを呼び出すこともできます。これを行うには、オブジェクト間の通信が必要になります。 オブジェクト間の通信Second Lifeのオブジェクトは、アバター同士が会話するのとほぼ同じ方法で相互に通信します。アバターは、近くにいるアバターに聞こえるように何かを「言う」(Say)ことができます。また、遠くに聞こえるように「叫ぶ」(Shout)こともできます。Second Lifeの通信は、すべて特定のチャンネルを通じて行われます。アバターは通常、チャンネル0を使って会話します。オブジェクトがチャンネル0でリスンしていれば、そのオブジェクトは近くにいるユーザーの話を聞くことができます。同様に、オブジェクトがチャンネル0で発言すれば、近くにいるユーザーはそれを聞くことができます。 高層ビルの各階には、エレベータを呼び出す緑色のボタンがあります。このボタンの仕組みはごく単純で、単にどの階でエレベータを呼び出しているかを伝えているだけです。これをエレベータのメニューとまったく同じ方法で行っています。 各階のボタンには
touch_start(integer total_number)
{
llShout(CHANNEL, "Floor 1");
}
このスクリプトではメッセージを叫んで(Shout)います。高層ビルは非常に高い場合があるので、 本稿では、Second Lifeでエレベータを作成する方法を紹介しました。これはほんの入り口にすぎません。LSLライブラリの数々のメソッドを使うと、ゲーム内のオブジェクトをほぼ無限に作り出すことができます。商取引を行って他のオブジェクトを販売するためのオブジェクトを作成したり、Second Life内のゲームで使う武器を作成したりできます。また、オブジェクトで外部のWebサーバとやり取りし、スクリプトで外部リソースを利用することもできます。 LSLについてさらに詳しく知りたければ、Linden Labs社が運用するLSLプログラミングに関するWikiで詳細な情報を得ることができます。 著者紹介Jeff Heaton(Jeff Heaton)
ライター、大学教員、コンサルタントとして活動中。4冊の著作があり、論文誌および雑誌で20を超える記事を発表。また、個人のWebサイトを管理し、人工知能とスパイダー/ボットプログラミングをはじめとする話題について情報発信を行っている。メールの宛先はjheaton@heatonresearch.com。
|