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

2007年06月21日

エレベーター2

あわわ 三日坊主してました

というわけで前回のエレベーターを改良してみようかと

はさまれっぱなしじゃかわいそー
前回のはひとまずスムーズに動かしただけで
ただ上下に箱が動くだけでした~ 箱~


なのでここはエレベーターらしく 

・ 中に行きたい階のボタンパネル
・ 各階のエレベーター外にボタン

つけてみましょか まずは頭ん中で構想~~



.
..
...
....

...(5分経過)...


うぃ!
中のボタンパネルはなんか普通にListでも作ってできそ~


でも各階のボタンからどうやってエレベーター本体と通信しよぅ????






.
..
...
....

...(10分経過)...


え~と エレベーター本体と各階のボタンをリンクさせて…

エレベーター2

エレベーターを動かすと…

エレベーター2


( ゚д゚)ポカーン


ダメじゃん 一緒に動いてるよ






.
..
...
....

...(5分経過)...


あぃ じゃリンクせずに本体と各階ボタンを別オブジェにして
各階ボタンにしゃべらすか…

エレベーター2

う~ん…これってエレベーター本体はlistenイベントが
常にぐるぐる回ってないと無理じゃない??

さすがに24時間回りっぱなしのlistenイベントはいかがかと…
サーバーさんに怒られそうだな うん却下






.
..
...
....

...(20分経過)...


あはw ボタンから物投げてみるか!
で本体にぶつかったらllDetectedNameかなんかで
投げた奴見つける! (゚Д゚)ゴルァ!! って

エレベーター2

Σ(・ω・;|||

下に投げるか上に投げるか誰が知ってんの?
ボタンからはエレベーターの位置はわかんないしな~~
とりあえず下に投げてみて地面にあたったら上に跳ね返る?
って地面に当たったかエレベーターに当たったかなんて区別付くの??

なんか無謀だしカコわるいので却下







.
..
...
....

延々とLSLの関数眺める…

...(20分経過)...


llEmailってオブジェクトにもメール投げれるじゃん!
ヽ( ゚∀゚)/ やたー これなら本体がどこにいようが関係ない~

エレベーター2

あぅ…メールが送信されるまでだいたい20秒…
受け取りに最大3秒…


はい却下 待ちきれません!





.
..
...
....
.....
......
.......
........

...(1時間経過)...


(*゚∀゚)ゞ すんごいこと思いつきました!


エレベーター2
ボタンが押されると…

1.押されたボタン自身がlisten起動

2.llRemoteLoadScriptPinで空っぽのスクリプトを
  エレベーターに投げて実行しちゃう



エレベーター2
空っぽのスクリプトを受け取ったエレベーターは

3.timerイベントで空っぽのスクリプトが稼働中かを
  llGetScriptStateで調べておいて 稼動してたら
  自分自身のlisten起動

4.でもどの階のボタンからスクリプトを投げられたかは
  わからないので『誰が呼んだの?』って全部のボタンに
  聞いてみる



エレベーター2
1の工程で呼び出し元の階のボタンはlistenが起動しているので…

5.ひとまずエレベーターから『誰が呼んだの?』を聞いて
  自分自身のlistenを停止させる
  他の階のボタンはlistenが元から動いてないので
  エレベーターの声は聞こえず~



エレベーター2
6.で呼び出し元の階のボタンがエレベーターに向けて
  『おいらが呼んだ~』って叫んでみると…

7.3の工程でlistenを起動していたのでエレベーターは
  ちゃんと6の声は聞こえる!
  声から場所を判断して目的高度をセット
  listenはこのとき止めちゃう



エレベーター2
8.で移動開始~~





いやぁ~ 相手のlistenを起動させるのにllRemoteLoadScriptPin
使ってキックさせるとはw 使い方思いっきり間違ってるような~~


でもSIMにも周りの人にも迷惑を掛けなさそうなので環境にやさしぃ うん



というわけで実際のオブジェにスクリプトを φ(..)カキカキ

エレベーター2

エレベーター2

実際には上みたいに動かすためにはかなりの下準備が必要だった…
エラいことになったので説明ははしょって… (ぇ

要はあらかじめ各階のボタンたちが自分のKeyと場所を
エレベーター本体に渡しておかないと エレベーター内の
行き先ボタンが作れないのね…

その辺はlistenllShouttimerを駆使してやり取りしました~



はい そんなこんなで…

↓これを親プリム(ルートプリムへ)


float   _MOVE_HEIGHT;
integer _MOVE_STATE         = FALSE;
float   _MOVE_SECOND;
float   _MOVE_VELOCITY      = 5.0;
float   _TIME_INTERVAL      = 0.1;
vector  _TARGET_POS;
integer _TARGET_ID;
float   _TARGET_MARGIN      = 0.3;
list    _TMP_LIST;
list    _FLOOR_NAME;
list    _FLOOR_KEY;
list    _FLOOR_HEIGHT;
string  _DEST_FLOOR_NAME;
float   _SETTING_TIMEOUT    = 20.0;
float   _DIALOG_TIMEOUT     = 15.0;
float   _REPLY_TIMEOUT      =  5.0;
integer _CURRENT_FLOOR;
integer _HANDLE;
integer _PIN                = 7699;
integer _CHANNEL            = -33;
key     _TOUCH_KEY;
string  _GRANDMA_SEARCH     = "where are my grandchildren?";
string  _GRANDMA_CONFIRM    = "who is calling?";
string  _GRANDCHILD_REPLY   = "hi, grandma. im calling!";
string  _BUTTON_SELECT      = "Please select the floor where you want to go.";
string  _SETTING_START      = "start setting... please wait about 15 sec.";
string  _SETTING_END        = "end of setting";
string  _DUMMY_SCRIPT       = "dummy";

move()
{
    vector pos   = llGetPos();
    _MOVE_HEIGHT = llList2Float(
                         _FLOOR_HEIGHT
                       , llListFindList(_FLOOR_NAME, [_DEST_FLOOR_NAME]));
    _MOVE_SECOND = llFabs((_MOVE_HEIGHT - pos.z) / _MOVE_VELOCITY);
    _TARGET_POS  = < pos.x, pos.y, _MOVE_HEIGHT>;
    _MOVE_STATE  = TRUE;
    _TARGET_ID   = llTarget(_TARGET_POS, _TARGET_MARGIN);
    
    llSetPrimitiveParams([PRIM_PHYSICS, TRUE]);
    llMoveToTarget(_TARGET_POS, _MOVE_SECOND);
}

keepHorizon()
{
    vector cur_rot = llRot2Euler(llGetRot());
    float  z_rot   = cur_rot.z;
    llRotLookAt(llEuler2Rot(< 0.0, 0.0, z_rot>), 0.5, 0.5);
}

default
{
    on_rez(integer param)
    {
        llResetScript();
    }

    state_entry()
    {
        llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
        llSetRemoteScriptAccessPin(_PIN);
        llSetScriptState(_DUMMY_SCRIPT, FALSE);
        state setting;
    }
}

state setting
{
    touch_start(integer num_detected)
    {
        llOwnerSay(_SETTING_START);
        _HANDLE = llListen(_CHANNEL, "", NULL_KEY, "");
        llShout(_CHANNEL, _GRANDMA_SEARCH);
        llSetTimerEvent(_SETTING_TIMEOUT);
    }
    
    listen(integer channel, string name, key id, string message)
    {
        vector pos   = (vector)message;
        float  z     = pos.z;
        _TMP_LIST   += [z, id];
    }
    
    timer()
    {
        integer i;
        float   diff;
        vector  pos = llGetPos();
        float   z   = pos.z;
        float   min;
        integer grand_floor;
        
        llSetTimerEvent(FALSE);
        llListenRemove(_HANDLE);
        
        _TMP_LIST    = llListSort(_TMP_LIST, 2, TRUE);
        for (i = 0; i < llGetListLength(_TMP_LIST); i += 2) {
            _FLOOR_HEIGHT += [llList2Float(_TMP_LIST, i)];
            _FLOOR_KEY    += [llList2Key(_TMP_LIST, i + 1)];
            if (i == 0 || diff > llFabs(llList2Float(_TMP_LIST, i) - z)) {
                diff = llFabs(llList2Float(_TMP_LIST, i) - z);
                min  = llList2Float(_TMP_LIST, i);
            }
        }
        
        grand_floor = llListFindList(_FLOOR_HEIGHT, [min]);
        
        for (i = 0 ; i < llGetListLength(_FLOOR_HEIGHT); i++) {
            if (i < grand_floor) {
                _FLOOR_NAME += ["B" + (string)(grand_floor - i)];
            } else {
                _FLOOR_NAME += [(string)(i - grand_floor + 1) + "F"];
            }
        }
        
        llOwnerSay(_SETTING_END);
        state waiting;
    }
}
        
state waiting
{

    state_entry()
    {
        llSetTimerEvent(_TIME_INTERVAL);
    }

    link_message(integer sender_num, integer num, string str, key id)
    {
        _TOUCH_KEY = id;
        state child_calling;
    }
    
    timer()
    {
        if (llGetScriptState(_DUMMY_SCRIPT)) {
            state grandchild_calling;
        }
    }
}


state child_calling
{
    state_entry()
    {
        _HANDLE = llListen(_CHANNEL, "", NULL_KEY, "");
        llSetTimerEvent(_DIALOG_TIMEOUT);
        llDialog(_TOUCH_KEY, _BUTTON_SELECT, _FLOOR_NAME, _CHANNEL);
    }    
    
    listen(integer channel, string name, key id, string message)
    {
        
        _DEST_FLOOR_NAME = message;
        llListenRemove(_HANDLE);
        state moving;

    }
    
    timer()
    {
        llListenRemove(_HANDLE);
        state waiting;
    }
}

state grandchild_calling
{
    state_entry()
    {
        _HANDLE = llListen(_CHANNEL, "", NULL_KEY, "");
        llSetTimerEvent(_REPLY_TIMEOUT);
        llShout(_CHANNEL, _GRANDMA_CONFIRM);
    }
    
    listen(integer channel, string name, key id, string message)
    {
        _DEST_FLOOR_NAME = llList2String(  _FLOOR_NAME
                                         , llListFindList(_FLOOR_KEY, [id]));
        llListenRemove(_HANDLE);
        state moving;
    }
    
    timer()
    {
        llListenRemove(_HANDLE);
        state waiting;
    }
}

state moving
{
    state_entry()
    {
        llSetTimerEvent(_TIME_INTERVAL);
        move();
    }
    
    at_target(integer number, vector targetpos, vector ourpos)
    {
        llTargetRemove(_TARGET_ID);
        llStopMoveToTarget();
        
        llSetTimerEvent(FALSE);
        keepHorizon();
        llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
        _MOVE_STATE = FALSE;
        
        llSetPos(_TARGET_POS);
        llSetScriptState(_DUMMY_SCRIPT, FALSE);
        state waiting;
    }
    
    not_at_target()
    {   
    }
    
    timer()
    {
        llSetPrimitiveParams([PRIM_PHYSICS, TRUE]);
        keepHorizon();
    }
}





↓これを子プリム(行き先ボタンのやつ:2つプリムあるけど同じスクリプト入れてます~)


default
{
    touch_start(integer total_number)
    {
        llMessageLinked(LINK_ROOT, FALSE, "", llDetectedKey(0));
    }
}



↓んでこれを孫プリム(親子とはリンクされているわけでないです~:ちなみに孫も全部同じスクリプト


integer _PIN                = 7699;
integer _CHANNEL            = -33;
string  _GRANDMA_SEARCH     = "where are my grandchildren?";
string  _GRANDMA_CONFIRM    = "who is calling?";
string  _GRANDCHILD_REPLY   = "hi, grandma. im calling!";
integer _HANDLE;
key     _GRANDMA;
vector  _MY_POS;
string  _DUMMY_SCRIPT       = "dummy";
float   _TIMEOUT_LOST       = 600.0;
float   _TIMEOUT_WAIT       =  10.0;
vector  _FLOAT_TEXT_COLOR   = < 1.0, 1.0, 1.0>;
float   _FLOAT_TEXT_ALPHA   = 1.0;
string  _FLOAT_TEXT_DEFAULT = "Please touch me if you use the elevator.";
string  _FLOAT_TEXT_CALLING = "Just a moment please... I'm calling the Elevator."; 
string  _FLOAT_TEXT_COMING  = "OK! Elevator is coming soon!";
                            
default
{
    on_rez(integer param)
    {
        llResetScript();
    }
    
    state_entry()
    {
        state lost;
    }
}

state lost
{
    state_entry()
    {
        _HANDLE = llListen(_CHANNEL, "", NULL_KEY, _GRANDMA_SEARCH);
        llSetTimerEvent(_TIMEOUT_LOST);
    }
    
    listen(integer channel, string name, key id, string message)
    {
        _GRANDMA = id;
        _MY_POS  = llGetPos();
        
        llListenRemove(_HANDLE);
        llShout(_CHANNEL, (string)_MY_POS);
        llSetTimerEvent(FALSE);
        
        state wait;
    }
    
    timer()
    {
        llListenRemove(_HANDLE);
    }
}

state wait
{
    state_entry()
    {
        llSetText(_FLOAT_TEXT_DEFAULT, _FLOAT_TEXT_COLOR, _FLOAT_TEXT_ALPHA);
    }
    
    touch_start(integer num_detected)
    {
        llSetText(_FLOAT_TEXT_CALLING, _FLOAT_TEXT_COLOR, _FLOAT_TEXT_ALPHA);
        llRemoteLoadScriptPin(_GRANDMA, _DUMMY_SCRIPT, _PIN, TRUE, FALSE);
        _HANDLE = llListen(_CHANNEL, "", NULL_KEY, _GRANDMA_CONFIRM);
        llSetTimerEvent(_TIMEOUT_WAIT);
    }
    
    listen(integer channel, string name, key id, string message)
    {
        llSetText(_FLOAT_TEXT_COMING, _FLOAT_TEXT_COLOR, _FLOAT_TEXT_ALPHA);
        llListenRemove(_HANDLE);
        llSetTimerEvent(_TIMEOUT_WAIT);
        llShout(_CHANNEL, _GRANDCHILD_REPLY);
    }
    
    timer()
    {
        llSetTimerEvent(FALSE);
        llSetText(_FLOAT_TEXT_DEFAULT, _FLOAT_TEXT_COLOR, _FLOAT_TEXT_ALPHA);
        llListenRemove(_HANDLE);
    }
}



↓最後にこれを親と孫のContentsの中に"dummy"という名前で放り込んでおく


default
{
    state_entry()
    {
    }
}





それぞれのプリムを適当に位置調整して親プリムをクリックすれば
初期設定が始まります~ その後はご自由に動き回れる~ わーーーい

これはエレベーター内のボタンパネル~(ちゃんと地下階も自動計算されるw)
エレベーター2

外のボタンを押してエレベーターが来るのを待つかっぱ
エレベーター2

んでもって やっぱり…
エレベーター2

あはw はさまれるのは直せないw

これ以上はむり~~ エレベーターはこれでしゅうりょ~

Zzz ( ̄~ ̄) ムニャムニャ


同じカテゴリー(スクリプト)の記事画像
ふきだし
ペット
打ち上げ花火
エレベーター
同じカテゴリー(スクリプト)の記事
 ふきだし (2007-08-13 12:20)
 ペット (2007-07-30 13:04)
 打ち上げ花火 (2007-06-23 08:50)
 エレベーター (2007-06-17 22:05)
Posted by かっぱ at 22:36│Comments(11)スクリプト
この記事へのトラックバック
同じような事で悩んでいる方がいて親近感がわいたので失礼ながら勝手にトラックバックを・・・親と子を個別に操作するのが非常に難しいですねぇ・・・・つまり、花火の弾部分を打ち上...
花火上がらず【酔っ払い放浪記】at 2007年06月22日 12:16
>>> 120
ゆかりちゃんと会ったんだけどさ、あの子工口すぎ( ;゜Д゜)
アイスとかチョコレートとかを俺の珍珍に塗りたくっていっぱいペロペロしてくれたよヽ(´ー`)ノ
アイス塗られた時...
チョコバーならぬチョコチンwwwwwww【ゆーた】at 2008年08月30日 19:43
この記事へのコメント
す、すご~い。
こんな仕組みになっていたとは・・・しかも図入りで分かりやすく解説されてますねー。
それにしても物作りって試行錯誤の連続ですね。

PS.河童さんのブログもお気に入りに追加させて頂きましたー。
Posted by scarecrowJACK at 2007年06月22日 04:28
すばらしい!天才河童ですねw
とうとうエレベーターが終了しましたか・・・。
Posted by ダミーくん at 2007年06月22日 13:52
シザさん ダミーさん

どうもです〜!
もの作り飽きないです〜
完璧に自己満足の世界ですがw
Posted by かっぱ at 2007年06月23日 00:34
カリスマ河童さん!お初です。
こちらのサイトを参考に作成中のダンスクラブに上に移動する「お立ち台」を」作成中です♪ 衝突関数を追加して移動距離の制限をかけようとなんとか頑張ってます!(アバタ対象は面白いので放置・・・)
これからも参考にさせて頂きますので頑張ってください!
Posted by yanyan at 2007年07月23日 10:24
> yanyanさん

あわわ 参考にされてるw
ヾ( ~▽~)ツ ワーイ♪ うれしいですー

お立ち台がんばってくださいねー^^
衝突で停止処理かぁ〜 そかー
そっちの方がスマートだったかも〜
d(>_< )ぐー


見てくださってる方もいるので
も少しスクリプト関係を充実させよ〜と

さっそく引きこもるかなぁ(T-T)
やっぱり引きこもり〜w
Posted by かっぱ at 2007年07月23日 17:23
はじめましてー。
ウチでもエレベーター設置したくて情報求めて彷徨っていたところ、こちらの記事に行き当たりました。
判りやすくて非常に為になる記事なので、参考(パクリ?)にさせて頂きました。m(_ _)m

ゴンドラを呼び出すための方法論ですが、「LSL流し込んでListen起動」のフロー読んでて気が付いた事があります。
記事では手順2にて空のスクリプトをリモートロードして、それを監視してリスナ起動し、呼出機と通信して呼出元を特定してますよね。
ですが、リモートロードで投げるスクリプトの中に、「2階から呼出だぜ」などと呼出元をリンクメッセージで伝えるコードを書いておけば、リスナ起動するまでもなくゴンドラは呼出元を知る事が出来ると思います。

アバターが挟まれてしまうのを防ぐ方法として、ウチでは現実と同じようにフロアにも扉を作りました。
ついでにゴンドラが居る位置を表示する表示器も付けてみました。
これらの機能を各フロアに付けると、ゴンドラから全フロアに逐一情報を送らなくてはなりません。
当初はリスナを使わないようにと全てリモートロードで情報伝達しようとしましたが、リモートロードだと一度に複数の対象へ同報することが出来ないのと、1回1回のディレイが長いのでリアルタイム性が失われて役に立ちませんでした。
仕方なく各フロアに1個ずつ常時リスナを使ってしまいました。
見た目的にはぐれいとなエレベータが完成したのですが、SIMへの負担という面で考えるとやっぱ不味いですかねぇ。
Posted by kundali at 2007年09月02日 23:04
> kundaliさん
w(゜ー゜;)wワオッ!!
すごーい。このスパゲッチコードを解読されちゃってるw。

リモートロードの中にリンクメッセージ!
そうか、その手がありましたね〜!全然思いつかなかった…。
新たな組み合わせを知れて幸せ〜w

常時listenを稼働させててそれが原因で
SIMが落ちるようなことはあり得ないと思いますが、
やっぱり精神衛生上よろしくないですよね〜。
でもkundaliさんみたいに『知ってて最小限で使う』のと
『知らずに無駄に使う』のは大きな違いだと思います。

SIMのことを考えて、「ごめんなさい、使っちゃいますね」の姿勢は
個人的には許される範囲だと思いますよ〜。個人的にはですが。
Posted by かっぱかっぱ at 2007年09月03日 01:02
エレベーターを調べててこちらにたどり着きました。テレポートやllSetPosが気に入らずどうにかしたいと思っていたところ、「まさにこれ!」という内容です。すごすぎる!
ここまで複雑になるとはw
参考にさせていただきたいと思います。(というかカスタマイズ?)m(_ _)m
Posted by TERRA at 2007年10月05日 20:19
> TERRAさん
どうぞどうぞ〜^^
なんかいろいろ変な記述してますが
結局はllMoveToTargetさえ使えれば
エレベーターは動かせますので
頑張ってくださ〜い。
Posted by かっぱかっぱ at 2007年10月06日 08:03
はじめまして。物理エレベーターで検索してきました〜。
わかりやすくって参考にさせていただきました。ありがとうございます。
ところで、このエレベーターをREZ-fauxに建物と一緒に入れておこうと考えていますけど、REZする度にスクリプトのリセットが必要になるんでしょうか?
エレベーターとは関係のない話かもしれませんが、ご教授お願いできませんか?
Posted by mana at 2011年07月21日 15:16
Hi,

We run an Instagram service, where we can increase your followers both safely and effectively.

We don't use bots – everything is done manually to attract real, targeted followers who care about your content.

The result? Increased brand awareness, higher engagement, and ultimately, more customers.

The price is just $60 (USD) per month.

If you would like more information, get back in touch.

Kind Regards,
Megan
Posted by Megan Atkinson at 2024年04月19日 19:38
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。