ソラマメブログ
QRコード
QRCODE
アクセスカウンタ
読者登録
メールアドレスを入力して登録する事で、このブログの新着エントリーをメールでお届けいたします。 解除は→こちら
現在の読者数 0人
オーナーへメッセージ

2007年11月13日

スクリプトあれこれ-その10- ポーズボール

今回はポーズボールを作ってみよう。

ポーズボールは、赤や青の丸いボールで、そこに"座る"と、
踊りだしたり、寝転がってごろごろしたりと、
そのボールにあらかじめ設定された動きをするものだ。
SLではおなじみだと思う。
前に作った、タッチしてダンスの、「座ってダンス」版と考えたらいい。

それでは、まず材料を用意しよう。
何か新しいオブジェクト(球形にして、赤や青色にすれば、それらしくなる・・・)を用意しよう。
そのオブジェクトの中に、適当な踊りのアニメーションを入れ、
そのアニメーションの名前を"dance"に変えておこう。
そして、新規のスクリプトを作成して、準備完了だ。
ここまでは、タッチダンスと同じだ。
まずは座ることの検知
スクリプトの大まかな構図は、
「座ったら、踊り始める。立ったら、踊りを停止する。」だ。
つまり、オブジェクトに座ったとき、立ったときというイベントに、
踊る、踊りを停止する、を書き込む。これなら簡単だ。

ところが・・・・

座った時、立った時というイベントは、実は存在しない。
いや、ない、というよりも、その時に、確かにイベントは生じるのだが、
それは、changedというなんだかよく分からないイベントが生じるのだ。

まずは、lslWikiのsitのところを見てみよう。
イベントのところに書いてあることは、
「座ったり立ったりするときには、changedというイベントが、フラッグ(旗)CHANGED_LINIKをもって、立ち上がる、」
となっている。
そこで、changedというイベントについてみてみよう・・・。
アバターが座ったり立ったりするときだけでなく、いろいろなことでchangedイベントは起こるようだ。
けれども、座ったり立ったりしたときにも確かにchangedイベントが生じるので、
このイベントが起こったときに、本当にアバターが座ったり立ったりしたのか、調べる、という手順になりそうだ・・・。

もう少しlslWikiのsitのところを見てみよう。
llAvatarOnSitTargetという関数が書いてある。
説明は、現在の"sit target"に座っているアバターのkeyを教えてくれる・・・これは使えそうだ。
llAvatarOnSitTargetについてもう少し詳しくみてみよう。

    key llAvatarOnSitTarget()

「もしアバターが"sit target"に座っていたらアバターのkeyを返し、そうでなければNULL_KEYを返す。」
これは、とにかく、アバターが座ってるかどうかはわかると言うことだ。
続きを見てみよう。じつは、これが曲者なのだ。
llAvatarOnSitTargetは、「llSitTargetによって定められた"sit target"に座ってる場合にだけ、アバターを検知する。」
llAvatarOnSitTargetを有効にするには、"sit target"を設定しなければだめなようである。
llSitTargetとは何なのか、これも見てみよう。

    llSitTarget(vector offset, rotation rot)

「"sit target"をプリムにセットし、プリムの中心からvector offsetだけ離れた位置に、rotation rotだけ回転してセットする。」
どうやら、"sit target"は、目に見えない「ざぶとん」のようなものをで、
llSitTargetは、これを指定した位置に置いてくれるみたいだ。

続きを見てみよう。「もし、vector offsetが、ZERO_VECTORであれば、"sit target"はクリアーされる。」とある。
つまり、vector offsetを、<0.0, 0.0, 0.0> (ZERO_VECTOR) に設定してはいけないということだ。
どういうわけだか、わからないが、とにかく、vector offsetをZERO_VECTORにすると、"sit target"は消えてしまうので、気をつけよう。

さらに、読み進めると、やはり、「"sit target"を設定した後で、llAvatarOnSitTargetは使用可能になる。」とある。
さっきから、何度か出てきてるが、とにかく、
llAvatarOnSitTargetを使用可能にするには、
あらかじめllSitTargetで"sit target"を設定しておく必要がある

と言うことだ。

さて、以上のように色々あるが、重要なことは、
アバターがオブジェクトに座っているかどうか知ることができる、ということだ。
これがわかれば、changedイベントで、アバターがオブジェクトに座ったり立ったりしたかどうかが検出できる。
その検出の仕方は次の通りだ。

ビフォアーアフター
changedイベントが起こったときにアバターが座ったり立ったりしたかどうかは、
changedイベントのビフォアーアフターを調べればいい。

changedイベントの直前、オブジェクトにアバターが座っているかどうか、
changedイベントの直後、オブジェクトにアバターが座っているかどうか、
をしらべる。
そして、「ビフォアー」→「アフター」が、
「座っていない」→「座っている」ならば、「座った」
「座っている」→「座っていない」ならば、「立った」
ことになる。

けれども、こう思う人がいるかもしれない。
アフターはすぐわかるけど、
ビフォアーはタイムマシンでもなければ、わからないよと。

ところがだ。changedイベントがおこったアフターは、それと同時に、
次のchangedイベントがおこるビフォアーでもあるのだ。
そこで、beforeとafterという変数を作って、その変数にアバターが座っていたかどうかの
ビフォアーとアフターをタイミング良く格納すればいいというわけだ。

それじゃあ、スクリプトに取り掛かろう。ビフォアーアフターの格納のタイミングは次のようになる。


key before = NULL_KEY;
key after = NULL_KEY;

default
{
    state_entry()
    {
        llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION); //llAvatarOnSitTargetを使用可能にするのに必要
    }

    changed(integer change)
    {
        after = llAvatarOnSitTarget(); //changedイベントのアフター。現在座っているアバターidを格納。

        //ここで、beforeとafterをしらべると、ビフォアーとアフターの状態がわかる。
        //なぜなら、beforeには、changedイベントが起こってからは値を格納していないので、
        //その前のchangedイベントで格納した値が入っている。

       before = after; //次のchangedイベントに備えて、現在座っているアバターidを格納。
    }
}


あとは、before、afterをしらべればよい。
これらがNULL_KEYならば、オブジェクトに座っていない
これらがNULL_KEYでなければ、オブジェクトに座っている
のだから、スクリプトは次のようになる。


key before = NULL_KEY;
key after = NULL_KEY;

default
{
    state_entry()
    {
        llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION);
    }

    changed(integer change)
    {
        after = llAvatarOnSitTarget();

        if (before == NULL_KEY && after != NULL_KEY) //座った時
        {
            llSay(0, "sit!");
        }
        else if (before != NULL_KEY && after == NULL_KEY//立った時
        {
            llSay(0, "stand up!");
        }

        before = after; 
    }
}


これで、オブジェクトに座ったとき"sit!"といい、立ち上がったとき"stand up!"と言うスクリプトが出来上がった。
実際に、座ったり立ったりしてみよう。どうだろうか。きっと、うまく"sit!"、"stand up!"と言っただろう。

ここまでできれば、あと、一息だ。

いよいよdance!
"sit!"と言う代わりに、踊りを始めさせてやればいい。
まずは、permissionsの要求をして、
OKが得られたらrun_time_permissionsイベントが起こるので、
このイベントで踊らせてやればいい。

ここで、一つ知っておかなければならないことがある。
オブジェクトに座っているアバターにアニメーションのpermissionsを要求した場合にかぎり、
アバターにはpermissionsの許可を求めるダイアログが示されず、
自動的に、permissionsは許可される。

実際、ポーズボールに座っても、踊らせていいかどうか、聞かれなくても勝手に踊りだすだろう。
どうして聞かれないのかなと思っていた人もいるだろうが、そういうわけなのである。

さて、そういうわけで、スクリプトは、座ったアバターだけにpermissionsを与え、
その瞬間permissionsは許可されて帰ってくるのだから、
これは、どう考えても、
run_time_permissionsで許可を出したアバターは、
座っているアバターと同一人物、と言うことになる。
だから、ややこしいことを考えなくていい。
すなおにpermissionsをくれたアバターを踊らせてても問題は起こらない。

もう一つ、踊らせる前に、アバターは座るポーズをとる。
そりゃそうだろう。だって、座るのだから。
これは、デフォルトで"sit"という名前のアニメーションが自動的に実行されるから座るポーズをとるのだ。
だから、これをストップしてから、"dance"というアニメーションを踊らせなければならない。

次に、"stand up!"の方だが、これは、単純に、踊りをストップさせればいい。
ストップさせるにもpermissionsは必要だが、
踊っているアバターからのpermissionsはすでに取得されており、
無効になることはない(別のpermissionsを受けることはない。)のだから、
改めてpermissionsを要求する必要はなく、そのまま踊りを止めさせてあげれば良い。

以上のことより、スクリプトを書き換えてみよう。


key before = NULL_KEY;
key after = NULL_KEY;

default
{
    state_entry()
    {
        llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION);
    }

    changed(integer change)
    {
        after = llAvatarOnSitTarget();

        if (before == NULL_KEY && after != NULL_KEY)
        {
            llRequestPermissions(after, PERMISSION_TRIGGER_ANIMATION);
        }
        else if (before != NULL_KEY && after == NULL_KEY)
        {
            llStopAnimation("dance");
        }

        before = after; 
    }

    run_time_permissions(integer perm)
    {
        llStopAinmation("sit");
        llStartAnimation("dance");
    }

}


さて、これでほぼ完成だが、
このオブジェクトの上に"dance"という文字が現れるようにしてみよう。
そして、踊ってるときは、この文字と、オブジェクトそのものが消えるように設定しよう。

文字が現れるようにする関数は、

    llSetText(string text, vector color, float alpha)

で、textは現したい文字、vector colorは文字の色、float alphaは文字の透明度だ。
この場合文字は"dance"としよう。色は、白なら<1.0, 1.0, 1.0>、透明度は完全な不透明なら1.0だから、
llSetText("dance", <1.0, 1.0, 1.0>, 1.0)となる。
文字を消したいときは、llSetText("", <1.0, 1.0, 1.0>, 1.0)と、文字をなくして同じことをすればいい。

オブジェクトを透明にする関数は、

    llSetAlpha(float alpha, integer face)

で、float alphaは、透明度、 integer faceはどの面を設定するかだ。
float alphaを1.0にすれば完全に不透明、0.0にすれば完全に透明にできる。
また、integer faceは、全面を示すALL_SIDESという定数にしておけばOKだ。

それでは、最後の仕上げだ。


key before = NULL_KEY;
key after = NULL_KEY;

default
{
    state_entry()
    {
        llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION);
        llSetText("dance", <1.0, 1.0, 1.0>, 1.0);
    }

    changed(integer change)
    {
        after = llAvatarOnSitTarget();

        if (before == NULL_KEY && after != NULL_KEY)
        {
            llRequestPermissions(after, PERMISSION_TRIGGER_ANIMATION);
            llSetText("", <1.0, 1.0, 1.0>, 1.0);
            llSetAlpha(0.0, ALL_SIDES);
        }
        else if (before != NULL_KEY && after == NULL_KEY)
        {
            llStopAnimation("dance");
            llSetText("dance", <1.0, 1.0, 1.0>, 1.0);
            llSetAlpha(1.0, ALL_SIDES);
        }

        before = after; 
    }

    run_time_permissions(integer perm)
    {
        llStopAinmation("sit");
        llStartAnimation("dance");
    }
}


最後に、アバターの踊る高さを調節する必要がある。
つまり、llSitTargetの"sit target"の位置のz値(上のスクリプトの赤字のところ)を
適当な値に調節してやれば、完成だ。

今回は、説明は長くなったが、そんなに難しくもなかっただろう。
スクリプトもシンプルだ。

ポーズボールの見本は、いくつかネットで見かけるが、
今回のものは、それらとは少し違うかもしれない。
たとえば、Mizさんの例では、アニメーションのオーバーライド(AO)にも対応した高級なやつだ。
厳密さでいえば、私の書いた例は十分ではないかもしれない。けれども、私にそんな上等なものは作れない。
まあ、プログラムも、百人百様っていう感じかな。それがまた、おもしろいところでもあるのだが。
けれど、もし不具合を見つけたら、ぜひとも教えてほしい。

じゃあ、今回はこの辺で。icon23

この記事へのトラックバックURL