02/25/2007

とりあえず動くポーズボールの作り方

ポーズボールというのは、アバターを座らせたり躍らせたりするためのスイッチのようなものです。椅子の上に丸いボールが置かれているのをよく見かけると思います。

ここではチュートリアルにあるスクリプトを利用して、実際のポーズボールの作成方法を紹介します。
 
用意するものは3つ。

1.アニメーションファイル
2.オブジェクト
3.スクリプト

このうちアニメーションファイルはSLの外で作成します。汎用ツールでもSL用に作られたツールでも作成可能です。今回は簡単のためにQAvimatorというソフトを使います。各OS版がでてますが、他はわからないのでWindows前提で話を進めます。
アニメーションの作成法はSLwiki(JP)でも紹介されています。
アニメーション作成(SL wiki JP)


1.QAvimatorセットアップ
公式サイトhttp://qavimator.org/からWindows版QAvimator(2007/02現在では「qavimator-install-2006-09-25.zip」)をダウンロードします。
そのまま解凍してセットアップファイルを実行、インストールします。

2.QAvimator起動・作成
QAvimatorを起動します。

Qavimator


今回は2こまのアニメーションなので、右下のフレーム数を「2」に設定します。
2フレーム目にアバターにとらせたいポーズを作成しますが、起動した状態で最後のフレームになっているのでそのままで大丈夫です。各パーツを選択した状態で右の「Rotation」や「Position」を変更してポーズを作っていきます。
このとき腰パーツの位置がアバターの座標となります。腰位置が高すぎるとポーズをとらせたときに体が浮いてしまったりします。

3.アニメーションファイル保存
ポーズが完成したらファイルに保存します。拡張子は「BVH」です。
拡張子は手打ちしないとダメそうだったので、例えばファイル名を「pose.bvh」などとします。

4.アニメーションファイルアップロード
セカンドライフビューワーを起動してログインします。
左上のfileメニューの3番目に「Upload Animation(L$10)というのがあるので、先ほど保存したアニメーションファイルを選択してアップロードします。
その際、LoopにチェックをいれPriorityを4にします。

5.アニメーションチェック
アップロードしたアニメーションは、下のメニューの一番右の「Inventory」→「Animation」に収納されています。
ファイル名右クリックで出るメニューから、「Play in World」(またはPlay Local)を選択すると、実際にアニメーションを試してみることができます。
ここでうまくいかない場合はアニメーションがうまく作れてないかもしれません。
また、アバターが浮いたり埋まってしまう場合はもう一度修正してからアップロードするか、場合のよってはスクリプトで補正できるかもしれません。

6.オブジェクト作成
今度はセカンドライフの中でオブジェクトを作成します。
下のメニューの中からBuild(または「立てる」)を選んで編集モードに入ります。create(または「生成」)を選んで適当に丸いオブジェクトを作成します。
オブジェクト作成の細かい操作方法ははじめてのオブジェクト作成(SL wiki JP)などで。

7.スクリプト作成
オブジェクト編集の「Content」で「New Script」を選択して新しいスクリプトをオブジェクト内に作ります。
「New Script」という名前のスクリプトができているので、中身をダブルクリックで開き、そこに書いてあるスクリプトは消してポーズボール用のスクリプトを書き込みます。
今回はLSL wikiのチュートリアルにあるスクリプトをそのまま使います。

現在元ページが工事中らしくて参照できないので、以下をそのままコピペしてください。

-------引用開始----------------

integer hidden = FALSE; // Stores whether the object is visible

default
{
state_entry()
{
llSitTarget(<0,0,1>,<0,0,0,1>); // Set the target one meter above the ground
llSetSitText("Pose!");
}

changed(integer change)
{
if(change & CHANGED_LINK) // If someone has sat on, or "linked," to this prim...
{
key agent = llAvatarOnSitTarget();
if(agent)
{
llStopAnimation("sit");
llStartAnimation("stand");
}
else
{
llStopAnimation("stand");
}
}
}

touch_start(integer total_number)
{
if(hidden)
{
hidden = FALSE;
llSetLinkAlpha(LINK_SET,1,ALL_SIDES);
}
else
{
hidden = TRUE;
llSetLinkAlpha(LINK_SET,0,ALL_SIDES);
}
}
}

-------引用終わり----------

さらに、このスクリプトで「dance1」となっているところを、自分のアニメーションの名前にします。(そのままだと「dance1」というもともとあるアニメーションが再生されます)
「Save」をクリックして保存し、エラーが出ていないことを確認します。

Script1


8.オブジェクトにアニメーションファイルを格納
先ほどのInventory内のアニメーションファイルを、ドラッグアンドドロップで「Content」のボックスに格納します。

Edit1

これで、ポーズボールの作成は完了です。


何かがおかしいとき
・アバターの向きや位置がおかしくなる
オブジェクトの向きを変えるか、スクリプトの最初のほうにある「llSitTarget(<0,0,1>,<0,0,0,1>); 」を調整してください。<0,0,1>が座標、<0,0,0,1>が向きになります。座標を調整することで、アニメーション作成で失敗してアバターが浮いてしまった、というのも直せる場合があります。
向きは欲しい向きを算出するのがめんどくさいので、編集モードでオブジェクトの向きを変えてしまうほうが楽だと思います。
参考:オブジェクトの回転に関する覚書

・ポーズボールの上に黄色い三角と「!」が表示される
エラーがでているので、その内容を確認します。
ビューワーのToolメニューから「Show Script Warning~」を選ぶとエラーの内容を確認することができます。でてこない場合はすでにその辺にでてるかもしれません。
考えられることは、コピペでミスをしている、アニメーションのファイル名が一致していない、などです。

・踊ってしまう
スクリプトで実行するアニメーションが「dance1」のままになっています。書き換えて見てください。


ちなみに私はエラー落ちしたり、立ち上がるときにまれに周りが真っ暗になったりしました。なのでどこか適正でないところがあるのかもしれません。

| | Comments (3)

02/07/2007

11.3. Definitions

"roll""pitch""yaw"といった言葉はよく、飛行機やボートにおける回転のモードを記述するのに使われます。それぞれx軸、y軸、z軸の回転に該当します。

z-axis .
yaw-axis /|\
| __. y-axis
._ ___| /| pitch-axis
_||\ \\ |\. /
\|| \_______\_|__\_/_______
| _ _ o o o o o o o |\_ ______\ x-axis
// ./_______,----,__________) / roll-axis
/_,/ // ./
/__,/

初歩的な物理学のコースでよく紹介される右手の法則は、これらの軸についての正回転を定義するのに使われます。右手の法則の使い方の例として、"roll(x軸)"の正回転について考えてみてください。
これらの回転がどのように飛行機を動かすかを可視化するために、右手の親指をx軸方向を指すようにして、飛行機のroll軸と平行になるように置いてください。そして、4本の指は手の平に折り曲げてください。そうすると、あなたの指は飛行機が回転する方向を指し示しています。


.-.--.--.--. __
/ / / / _ \ / \
(-(- (- (- ( | _________|______\ axis of
\.\._\._\._) | | / rotation
| \:__,---. \|/
| | + positive
\ .,_.___.' rotation
\_ ^ `.__,/
| /
| |

乗り物を制御する多くのパラメータはVEHICLE_BEHAVIOR_TIMESCALEで表されます。
乗り物の挙動の"timescale(時定数)"は一般的には、(何をさせたいかに関わらず)乗り物の挙動に対して押したり、カーブさせたり、もしくは別の影響を与え、その動作の大きさをe分の1にする時間です。
ここで"e"は自然対数の底(約2.718281828)です。

つまり、乗り物に希望通りの動作をさせているときに対する、指数的な減衰時間の目安であると言えます。

もし乗り物のレスポンスをとてもよくしたいのであれば、時定数を1秒やそれ以下という風に短く、そしてもしこの影響を無効にしたいのであれば300(5分)やそれ以上といった非常に大きな値にしてください。
ひとつ注意することは、安定性の問題から、通常は最小値に制限がありたいていは0.1秒のオーダーです。
時定数を0にすることは安全で最小値に設定することと同義です。時定数に特徴付けられたいかなる挙動も、効果が表れるまで丸一日かかるほど時定数を大きく設定してしまうことで効果的に無効にできます。


補足:超訳してしまいましたが例えばある初速度vを物体に与えたとすると、動き出した物体は最初はvで進んでいきますがだんだんと速度が落ちていき、時定数で設定した時間後にはv/eの速度になってしまいます。
現実で異動する物体が摩擦や空気抵抗でだんだん速度が落ちていくのを、このようにして模擬的に再現しているのです。
ここにあるように時間をものすごく短く(または0に)すればものすごく摩擦が働いているような状態になって一瞬でとまります。逆にものすごく長くすると、実際にはこの効果は働いているのですがその時間が長くなるため効果は出ていないように見えます。

| | Comments (2)

11/30/2006

Linden Script Language目次

<LSL wiki日本語訳>
チュートリアル - LSL101(プログラミング初心者向け)
  chapter1/chapter2/chapter3/chapter4/chapter5/chapter6


チュートリアル - Vehicles(乗り物作成)
11. Vehicles
11.1. Overview
11.2. Warnings
11.3. Definitions
11.4. Setting the Vehicle Type
11.5. Linear and Angular Deflection
11.6. Moving and Steering the Vehicle
11.7. The Linear Motor
11.8. The Angular Motor
11.9. Using the Camera to Steer
11.10. The Vertical Attractor
11.11. Banking
11.12. Friction Timescales
11.13. Buoyancy
11.14. Hover
11.15. Reference Frame
C. Constants
C.24. Vehicle Parameters
C.25. Vehicle Flags
C.26. Vehicle Types


<その他>
オブジェクトの回転に関する覚書
その1/その2

とりあえず動くポーズボールの作り方

| | Comments (0) | TrackBack (1)

07/14/2006

11.2. Warnings

乗り物についてはまだ開発中であり、SLの将来バージョンでは変更される可能性があります。安定性と安全性をより確実なものにする必要があるため、動作の細かい部分のいくつかは変更されるでしょう。特に、追記にある制限やデフォルトは変更される可能性が高く、長期的に見ると信頼できないものになっているでしょう。

オブジェクトに衝撃や力を与えるような他のスクリプトの呼び出し(特にllSetBuoyancy、llSetForcellSetTorquellSetHoverHeight)を、乗り物の動作と一緒に使うことはおすすめしません。

以下のメソッドは不安定性を起こさないと思いますが、乗り物と競合を起こして予期せぬ結果や矛盾を引き起こす可能性があるので、自己責任のもとで利用してください。 
llLookAt、llRotLookAt、llMoveToTargetllTargetOmega

乗り物に関するバグを発見したら、報告する方法のひとつとしては、乗り物とスクリプトのコピーをコメントかノートカードに問題を書いてAndrew Lindenに渡してください。
すべての依頼品には "Bugged Vehicle XX"と名前をつけてください。XXはあなたのセカンドライフイニシャルです。乗り物とスクリプトはできるだけ早く試験されるでしょう。

| | Comments (0)

11.1. Overview

スクリプトが組み込まれたそれぞれのオブジェクトはある乗り物としての動作を持っていて、その動作はライブラリから呼び出されるllSetVehicleTypellSetVehicleFloatParamllSetVehicleVectorParamllSetVehicleRotationParamllSetVehicleFlagsllRemoveVehicleFlagsによってコンフィグすることができます。

スクリプトが呼び出すこれらの関数の詳細は上のリンクにありますが、ここで注意すべき重要なことは乗り物の動作は、乗り物の処理の仕方を変更するたびに調整される、いくつかのパラメータをもっていることです。
選ばれる値によって、乗り物はボートのように水中で方向を変えたり、そりのようにレール上を走ったりします。

乗り物フラグ(vehcle frags)を設定すれば、いくつかのデフォルトの動作を期待できます。そのうちのいくつかは、ある動作が利用可能になったときのみ効果を持ちます。たとえば、VEHICLE_FLAG_HOVER_WATER_ONLYは乗り物が地形の高さを無視するようにしますが、ホバリングしているときのみ高低差を作ります。

| | Comments (0)

06/20/2006

オブジェクトの回転に関する覚書 その2

さて、オイラー表記できる回転は関数llEuler2Rotでrotation(四元数)に変換してくれるからいいとして、問題は軸の方向と回転角だけがわかっているとき実際に四元数でどう記述するのか、です。
例えばある方向に傾いたまま回る独楽を作りたいなんてときです。

残念ながらこの場合は、少しややこしい計算を行わなければなりません。

規格化された軸の方向を(a,b,c)とし回転角をθとすると、四元数(x,y,z,s)は

x = a ・sin(θ/2)
y = b ・sin(θ/2)
x = c ・sin(θ/2)
s = cos(θ/2)

となります。なぜ角度がθ/2なのかは直観的には、実際の計算は似たような形のものを2回掛けているからです。

 
詳しくはここなど。

物理のかぎしっぽの四元数
http://www12.plala.or.jp/ksp/mathInPhys/quaternion/
 
 

この若干面倒な計算のためのサンプルスクリプトがLSL wikiにあって、次のようになります。


rotation make_quaternion( vector axis, float angle )
{
vector unit_axis = llVecNorm( axis );
float sine_half_angle = llSin( angle/2 );
float cosine_half_angle = llCos( angle/2 );

rotation quat;
quat.x = sine_half_angle * unit_axis.x;
quat.y = sine_half_angle * unit_axis.y;
quat.z = sine_half_angle * unit_axis.z;
quat.s = cosine_half_angle;

return quat;
}

 

axisに回転軸の方向(規格化されてなくてもよい)・angleに回転角を与えればrotation quatが計算されます。

| | Comments (0)

06/16/2006

オブジェクトの回転に関する覚書

プリミティブ(オブジェクト)を回転させるとき、

vector eul = <0, 0, 45>; //z軸周りに45度回転するというオイラー表記
eul *= DEG_TO_RAD; //とりあえずラジアンに変換
rotation quat = llEuler2Rot( eul ); //オイラー表記を四元数に変換
llSetRot( quat ); //回転の実行

とします。
非常に数学的な操作を含んでいるので、一行ずつ解説を加えていくことにします。
 


■vector eul = <0, 0, 45>;

x軸を周りにα、y軸周りにβ、z軸周りに回転させるとき、<α,β,γ>と書き、これをEuler表記といいます。値が3つ並んでいるので、変数の型はvector(ベクトル)です。ちなみに、この表記をしたときは必ずx軸周り→y軸周り→z軸周りの順に回転が行われます。
(試してみるとわかりますが、回転の順序を変えると異なる結果になります。)
 


■eul *= DEG_TO_RAD;

角度はラジアンで表す必要があります。360[度] = 2π[ラジアン]なので、45度はπ/4[ラジアン]になります。DEG_TO_RADというのはLSLにはじめから用意されている定数(constant)で、"2π/360"と同じ意味です。
もちろん最初からラジアンで<0, 0, π/4>としておけば、この変換は必要ありません。

 

■rotation quat = llEuler2Rot( eul );

オイラー表記に対抗して(?)もうひとつ回転の表現方法があります。
それは回転軸の方向(x,y,z)と回転角度θを指定してやる方法で、3回必要だった計算が一回で済むようになります。そのため、LSLの内部ではこちらの方法が用いられています。

オイラー表記からの変換は、<α,0,0>などの場合には非常に簡単です。しかし<α,β,γ>などの変換はそう簡単にはいきません。

<α,0,0>   → 回転軸(1,0,0)・回転角度α
<0,β,0>   → 回転軸(0,1,0)・回転角度β
<0,0,γ>   → 回転軸(0,0,1)・回転角度γ
<α,β,γ> → 回転軸(?,?,?)・回転角度?

もちろん実際には変換する複雑な計算式があって、計算が得意な彼らはいとも簡単にやってのけます。

ところで突然ですが、この後者の表現方法をつかうために四元数というものを考えます。スクリプト中のquatというのはquaternion(四元数)のことです。回転はすべて四元数で表されます。細かい話はおいといて、数字が(x,y,z,s)と4つ並んだものが四元数です。

※ここでrotation(回転)という言葉は、変数の型の一種類という意味も持つようになります。
変数の型がvector(ベクトル)である、というときその変数は(x,y,z)の3つの値で表されるのと同様に、変数の型がrotation(回転)であるというときは、その変数は(x,y,z,s)の4つの値で表されます。

四元数は物理系の人ならば、特殊相対性理論で見かけたことがあると思います。最近は工学にも利用されているようです。四元数に関しては機会があれば詳しく説明するとして、兎に角llEuler2Rotという関数はこの変換を行っています。

 

■llSetRot( quat );

そして最後にllSetRotで回転を実行します。回転を実行するというよりは、文字通りプリミティブの"回転"というパラメータをセットするといったほうが正確かもしれません。


ちなみに、4行をまとめて

llSetRot(llEuler2Rot(<0, 0, 45*DEG_TO_RAD>));

という風に書いてもかまいません。
ところでこのままだと、オブジェクトの初期状態に関わらず結果は同じになります。先に述べたように、回転を実行するというよりはパラメータをセットするだけなので、当たり前といえば当たり前です。相対的に角度を変化させたい場合は、llGetRotを用いて現在の回転のパラメータを取り出す必要があります。


vector eul = <0, 0, 45>; //z軸周りに45度回転するというオイラー表記
eul *= DEG_TO_RAD; //とりあえずラジアンに変換
rotation quat = llEuler2Rot( eul ); //オイラー表記を四元数に変換
rotation quat0 = llGetRot();//実行前の回転の状態を取り出す
llSetRot( quat * quat0); //回転の実行

 
4行目でその操作を行っています。取り出される回転の状態も四元数であるため、変数の型はrotationです。
実行前の状態に、実行したい回転を左から掛けることで相対的な回転を行うことができます。なぜ掛け算かということは、たとえば回転行列などを思い出してみるとよいかもしれません。そして、勘のよい方は気がつくと思いますが、この掛け算の順序は逆にすることはできません。

ちなみにこれも一行にまとめることができます。

llSetRot(llEuler2Rot(<0, 0, γ>) * llGetRot());

| | Comments (1) | TrackBack (0)

05/11/2006

LSL101 Chapter6

chapter1/chapter2/chapter3/chapter4/chapter5/chapter6
 


Chapter6:簡単なポーズボールの作り方

ポーズボール?ポーズキューブ?
 
 
以上のことを考慮すれば、有用であろうスクリプト(ポーズボール)を実際に書くことが出来ます。


ポーズボールはセカンドライフにおいてアニメーションを作ろうとすれば必ず必要になります。簡単なものでは、以下の4つのパーツが必要になります。

1) 座る
2) ポーズボールを隠す/表示する
3) アニメーション本体
4) アバターをアニメーションさせる

この簡単なチュートリアルはデフォルトのアニメーションを使ったポーズボールの作成の助けとなるでしょう。

もう一度始めから
新しいスクリプトを作成してください。このスクリプトに戻りましょう:

default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
    }

touch_start(integer total_number)
{
llSay(0, "Touched.");
}
}


次に、ポーズボールが現れたり消えたりする必要があります。これは簡単にできます。llSetLinkAlphaを使えば、触れるだけでオブジェクト全体を消したり出現させたりできます。ここでブーリアンに挑戦してみましょう。

integer hidden = FALSE; // オブジェクトが現れている状態かどうかを記録します

default
{
    state_entry()
    {
        llSitTarget(<0,0,1>,<0,0,0,1>); // ターゲットをプリムの中央から1メートル上にセットします
        llSetSitText("Pose!");
    }

touch_start(integer total_number)
{
if(hidden)
{
hidden = FALSE;
llSetLinkAlpha(LINK_SET,1,ALL_SIDES);
}
else
{
hidden = TRUE;
llSetLinkAlpha(LINK_SET,0,ALL_SIDES);
}
}
}


 
 
素晴らしい!コンパイルして座って見てください。パーミッションが設定されてないという青い警告バーがでるはずです。

パーミッション?一体何のことでしょうか?アクションの中には、まずパーミッションによる承諾を得る必要があるものがあります。ここで例をいくつか見てください。

run_time_permissionsとllRequestPermissionsを使ってポーズボールを完成させましょう。

integer hidden = FALSE; // Stores whether the object is visible

default
{
    state_entry()
    {
        llSitTarget(<0,0,1>,<0,0,0,1>); // Set the target one meter above the ground
        llSetSitText("Pose!");
    }

changed(integer change)
{
if(change & CHANGED_LINK) // If someone has sat on, or "linked," to this prim...
{
key avataronsittarget = llAvatarOnSitTarget();
if( avataronsittarget != NULL_KEY ) //Someone is sitting on the object
{
// Comment out this code:
//llStopAnimation("sit");
//llStartAnimation("dance1");
// Before animating, first check if we have permission to do so:
if ((llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) && llGetPermissionsKey() == avataronsittarget) {
// If we do, we can animate:
llStopAnimation("sit");
llStartAnimation("dance1");
} else {
// If we dont, ask for them:
llRequestPermissions(avataronsittarget, PERMISSION_TRIGGER_ANIMATION);
// We'll animate in the run_time_permissions event, which is triggered
// When the user accepts or declines the permissions request.
}
}
}
}

run_time_permissions(integer perm)
{
if(perm)
{
// Place the code here!
llStopAnimation("sit");
llStartAnimation("stand");
}
}

touch_start(integer total_number)
{
if(hidden)
{
hidden = FALSE;
llSetLinkAlpha(LINK_SET,1,ALL_SIDES);
}
else
{
hidden = TRUE;
llSetLinkAlpha(LINK_SET,0,ALL_SIDES);
}
}
}

 

おめでとう!初めてのスクリプトを完成させLSLスクリプトの世界への最初の一歩を踏み出しました。 
あなたが迷ったときや解決の方法を知りたくなったら、いつでも参考にしてかまいません。
 
 
chapter1/chapter2/chapter3/chapter4/chapter5/chapter6

| | Comments (0)

05/10/2006

LSL101 Chapter5

chapter1/chapter2/chapter3/chapter4/chapter5/chapter6

 
 
Chapter5:主要なパラメータ

Particles and SetText and Spam, Spam, Spam, Eggs, SetText and Spam, Spam Spam and...
 
 


スクリプトによってできる便利なことのひとつに、プリミティブのプロパティを変化させることが出来るということが挙げられます。パラメータのいくつかを簡単に紹介しましょう。

すべての変更されたプロパティは(スクリプトが削除されれても)永久的に保持されるので、使う前にはあなたの作業をコピーして保存するのを忘れないでください!
 
 

Floating Text(テキスト表示)
llSetTextは最も簡単なパラメータです。プリムにfloating textを付け加えることが出来ます。
 
 

Particles and Textures(パーティクルとテクスチャ)
llParticleSystemは、比較的すぐ出会う複雑なシステムのひとつです。幸運にも多くのレジデントがパーティクルシステムの毒沼地帯に突っ込む道から脱出しています。そんな例題はこちら。より効果的なのはこちらです。
llCollisionSpriteはオブジェクトが何かにぶつかったとき(またはぶつかられたとき)のスプライト表示を変更します。
llSetTextureAnimを使えばテクスチャアニメーションをセットできます。
 
 

Sounds(音声)
llLoopSoundはオブジェクト内でサウンドをループさせ続けることができます。
llPlaySoundはオブジェクトを音源としてサウンドを一度だけ再生させることができます。
llTriggerSoundはサウンド再生のトリガーですが、オブジェクトをは関係なしに再生されます。そのため、音声はオブジェクトに追従しません。
CollisionSoundはプリムが何かにぶつかったとき(またはぶつかられたとき)にサウンドを変更します。
 
 

Sit Targets and Camera Stuff(座る位置とカメラ)
llSitTargetでプリムに対して座る位置を変更することができます。
llSetSitTextllSetTouchTextはそれぞれのアクションをパイメーニューから選択したときに表示されるテキストを編集することができます。
さらにプリムに座ったときにカメラがどのように動くかを編集することも出来ます。
 
 

Script-Related Goodies(スクリプト間のやりとり)
llSetRemoteScriptAccessPinllRemoteLoadScriptPinと共に用いられ、オブジェクトにスクリプトを送ることが出来ます。
 
 

Other Primitive Parameters(その他)
llSetPrimitiveParamsにはその他すべての重要なプリミティブの項目が含まれいます。形状、サイズ、外見、位置、角度、台所のシンク、スケールなど・・・
詳しくはこちらです。

 
 
chapter1/chapter2/chapter3/chapter4/chapter5/chapter6

| | Comments (0)

05/09/2006

LSL101 Chapter4

chapter1/chapter2/chapter3/chapter4/chapter5/chapter6
 
 


Chapter 4: ロジック

"What do you mean invalid parameters?! 9,000 gigs of RAM and it can't answer a simple question!" - Earthworm Jim

LSLは頑丈な言語ですが、一度ものの作り方を覚えてしまえば思うように操ることが出来ます!
このセクションでは変数、構文、繰り返しその他便利な機能の使い方と内部での働きを教えることにしましょう。


Everyone that knows C or C++ is dismissed, as LSL resembles that to the letter.


変数の再考

ここで働きをよりよく理解するために、変数について少しおさらいをしましょう。

C++と同様、データを受け取るための変数は左側に書きます。残ったスパムは右へ置いておいてください。例えば:

integer this = 1; // "this"に"1"を格納します
integer two = 2; // Stores "2" into "two"

this = 1 + 2; //  "this"に"1+2"または"3"を格納します
this = two; //  "this"に"two"の値を格納します


典型的に、変数の演算(1+2など)はイベントか関数内部でのみ行われます。あなたがいとも簡単に変数を格納できても、コンパイラが失敗してひっくり返ることもあるでしょう。
このような理由から、state_entryはかなり便利かもしれません。

そのほかにも変数を変化させるために有用な特別なコマンドがいくつがあります。Linden関数に加えて横切ることになるであろう対になるコマンドがあります:


integer i = 0; // Just a quick variable

++i; // Increments (adds one to) the value of i
i++; // Same thing, only it does so after the line of code is executed

--i; // Decrements (removes one from) the value of i
i--; // Same thing, except it happens after.

i += 1; // Shorthand for "i equals i plus one." Very handy.
i -= 1; // "i equals i minus one."
i *= 1; // "i equals i times one."
i /= 1; // "i equals i divided by one."

i = TRUE; // "TRUE" is a constant for 1.
i = FALSE; // "FALSE" is a constant for 0.


イコールとダブル・イコール

あなたはコードのある部分には1つだけイコール(=)が使われているのに対し、他では2回繰り返されている(==)のに気がついたでしょうか。これは意図してやったことです。

単一のイコールは、上記のように値に対して変数を宣言するのに用いられています。ダブル・イコールはある値に対する変数を評価するのに用いられています。一般的には繰り返しやif-else構文の中で用いられます(後述)。

True/FalseとIf/Else構文の記述

IfとelseはLSLの肉とポテトです。

構文を記述する前に、ifをこんな風にはじめてみましょう:


if(TRUE)
{
}


括弧{}と"TRUE(真)"に注意してください。これがあるのには理由があります。If構文は処理される際に、TRUE(1)と評価されるという条件が必要です。もしこの条件が満たされなければ、{}内のコードは完全に無視されます。

LSLではif構文は0よりも大きければどのような値でも可能です。例えば"if(15)"でも内部のコードは動くでしょう。これは一部のコード作成者にとっては注意すべきことです。

if構文は必ずしも後ろの{}を必要としません。時には完全に省略されます。その場合は、コードの次の行が条件節とみなされます。 - つまり、条件が満たされたときのみ走ります。


どうやってその条件を満たせばいいのでしょうか?それにはいろいろな方法があります:


integer one = TRUE;
integer zero = FALSE;

if(!one)
{
// これは決して実行されません。LSLでは!または"not"コマンドは
// 条件を反転させます。"not True"は"False"に等しく、反対に"not False"は"True"に等しくなります。
}
if(!zero)
{
// つまり、ここのコードは走ります。
}

if(one == TRUE)
{
// もし"one"が真であれば、ここでの記述は実行されます。
// ダブル・イコールは、値が一致すれば"真"を返します。
// 一致しなければ"偽"を返します。
}
if(zero == FALSE)
{
// なのでこれも実行されます
}

if(zero < one)
{
// また違った条件分がでてきました。これは"真"です。
// なぜなら"zero"は"one"より小さいからです。
}

key stuff = "Yar";
if(stuff)
{
// 面白いことに、条件としてキーや
// 文字列を与えることもできます。やってみてください!
}


ひとつif構文を置けば、その後に直接else構文を置くことができます。


単純にelseだけの場合、そのelseの前にあるif構文の実行に失敗したときに実行されます。また"else if"として連鎖を作ることも可能です。


例えば:

if(FALSE)
{
}
else if(FALSE)
{
}
else
{
    // ここのコードだけが実行されます。
}


より詳細な情報は、ifElseの項目を参照してください。


AndとOr

同じコマンドに、まったく違う実行。
Same commands, vastly different execution.

単一のanmpersand(&)はバイナリのAND(理論和)です。つまり、現在の変数のビットを評価します。

単一のvertical line(|)はバイナリのORです。この手軽な変数は要求されたビットを反転させます。

2つ並んだ&や|はANDやORの比較です。これらはifや繰り返し構文の中で用いられます。


例:

if(change & CHANGED_LINK)
{
    // If change is greater than zero, and the bits of CHANGED_LINK are on, do stuff.
}

llSetStatus(STATUS_PHANTOM | STATUS_PHYSICS, TRUE);
// Using Phantom + Physics bits to define a status.

if(TRUE && FALSE)
{
// Will never run. Both parts must be TRUE.
}

if(TRUE || FALSE)
{
// Will run, since only one part needs to be TRUE.
}


全くわかりませんか?ここここに挑戦してみてください。

繰り返し

繰り返しにはいくつかの方法があります。これらはほとんどC++からそのまま持ってくることが出来ます。

"while"ループは条件が真である限り走り続けます。ifと同じように、偽であればコードは実行されません。ifと違っている点は、条件が変わらない限り永遠に実行され続けることです。


例えば:

while(TRUE)
{
    // 無限に実行されます。
}

integer i = TRUE;
while(i == TRUE)
{
// 一度だけ実行されます。
i = FALSE;
}


"do-while"ループは基本的に常に一回は実行されるwhileループです。


do{
// 何が何でも実行します
}
while(FALSE);


"for"ループは3つのパラメータを用いて、簡単なイベントの流れを作ります。こんな風に:

integer i;
for(i = 0; i < 10; ++i)
{
    // iは0からスタートします。iが10未満の間繰り返し、それぞれの繰り返しごとにiに1を加えます。
    // ここは10回実行されます。
}


わからなくなった?ここに挑戦してみてください。

値を返す関数

関数の中には値として扱われるものもあります。例えば、 "number = llSin(2);"というのを見ることもあるでしょう。他の関数は値を返しませんが、ある関数は値を返します。これらの関数はまるで値であるかのように扱われます。

ここでどの関数が値を返すのか見ることが出来ます。

グローバル関数

グローバル関数(またはユーザー関数)も作り出すことができます。これらの関数はstateの外のみに作成でき、このような感じです:

float i_am_a_function(integer item)
{
    // Here's what we just defined. This function returns a float value.
    // It also accepts one parameter, which is defined here as "item"
    // "item" will act as if it has been declared, since it can be in the start of a function like this.
    item = 2;

// To call this function in the code, you would write something like "i_am_a_function(1)"

// Because this function returns a value, you MUST include this line:
return 0.0; // Returns a float.
}

State

stateはとても便利です。既にすばらしいチュートリアルがあるので、そちらに行ってみるというのはいかがですか?

演算子の順序

算数やif構文では、あるコマンドは特別な順序で実行されることに注意してください。
















演算子(上にあるものほど先に実行されます) Description
() [] . Parentheses, Square Brackets, Dot Operator
! ~ ++ -- NOT, One's Compliment, Prefix Increment, Prefix Decrement
* / % Multiply, Divide, Modulus
+ - Addition, Subtraction
<< >> Left Shift, Right Shift
< <= > >= Less Than, Less Than Or Equal To, Greater Than, Greater Than or Equal To
== != Comparison Equal, Comparison Not Equal
& Bitwise AND
^ Bitwise XOR
| Bitwise OR
&& Comparison AND
|| Comparison OR
= += -= *= /= %= ++ -- Value functions, Suffix Increment, Suffix Decrement


一般的に、もし演算子の順序がわからないようならたくさんの括弧を使って閉じてしまうのがよいと思われます。


ふー、長かった。そうでもないですか?
 
 
chapter1/chapter2/chapter3/chapter4/chapter5/chapter6


| | Comments (0)

より以前の記事一覧