2007年12月09日
回転タイプは面倒だった。
う~。。。思ったより、ずっと面倒だった。
何とかできたけど。。。止めれば良かったかも?

回転マンタの機能をおさらいすると、
1.サイズ変更機能(全長2.5m,5m,7.5m,10mの4段階)
2.回転半径変更機能(1m~25m)
3.回転方向変更機能
の3つになります。
本来であれば、ダイアログから此処の設定を指定時に変われば一番良いのですが、それが困難でした。
理由は、マンタが4パーツから構成されており、それぞれのパーツ位置調整が難しいからです。
例えばマンタだけで考えれば、マンタの胴体(ルートになる)を中心に、各パーツの位置を調整すれば良いのですが、回転タイプではルートが回転軸になってしまうため、回転軸との相対位置では、マンタとしての構成パーツの位置が単純には合わないのです。
例えば、フリームーブタイプの場合のサイズ調整機能は以下のような感じになっています。
float f = 変更後の大きさ/変更前の大きさ; //体長の変更比率を求める。
llMessageLinked( LINK_SET, status, (string)f, NULL_KEY);
このリンクメッセージを受信して、変更比率からllSetScaleで大きさを変え、更にllSetPrimitiveParamsで位置を微調整しているのです。
link_message(integer sender_num, integer st, string msg, key id){
f = (float)msg;
llSetScale(llGetScale() * f);
llSetPrimitiveParams([PRIM_POSITION, llGetLocalPos() * f]);
}
ここで位置の微調整に使っているのがllGetLocalPos() です。つまりルートからの相対位置に対して、大きさ変更による比率を元に調整している訳です。
これが回転タイプだと使えなくなってしまうのですね。ルートが回転軸ですから、そこからの相対位置を元に調整したのではあわなくなってしまいます。あくまで、マンタ本体の中心を基準に調整しないと駄目ですからね。
回転方向を変えるに至ってはお手上げです。なにせ、マンタの向きを逆にしないといけません。すると、今まで右側にあったヒレは左側へ移動する事になります。尾びれも反対側に来ます。
回転の位置が苦手の方向音痴ゴンベとしては、こうなっては何が何やら?訳が分からずお手上げ状態です。
で、結局Sculpted Dolphins Shop方式で、ダイアログの設定内容を元に、次の手順で反映させる方式に至った訳ですね。
1.ダイアログで設定内容を入力
2.マンタ側にダイアログで設定した内容をパラメータで渡して、標準のマンタオブジェクトをRez
3.マンタ側はパラメータ内容を元に、サイズ調整と半径の位置へと移動
4.マンタと回転軸をリンク
5.回転開始
となる訳です。
そして、タッチして再設定したい時は、一旦マンタを消滅させて、再度Rezして反映させると言う事です。
しかし、これもけっこう面倒なスクリプトでした。
リンク設定・解除のパーミッションを取得したり、メッセージ交換でUUIDを受け取ったり、更に厄介なのは自爆時に回転軸を巻き込んで自爆してしまい、全てが消えてしまうとか・・・(T_T)ウルウル
時には、マンタの片翼だけ大きさが違うとか・・・(T_T)
とにかく焦りまくりでした。(^_^;)
何とかできたけど。。。止めれば良かったかも?

回転マンタの機能をおさらいすると、
1.サイズ変更機能(全長2.5m,5m,7.5m,10mの4段階)
2.回転半径変更機能(1m~25m)
3.回転方向変更機能
の3つになります。
本来であれば、ダイアログから此処の設定を指定時に変われば一番良いのですが、それが困難でした。
理由は、マンタが4パーツから構成されており、それぞれのパーツ位置調整が難しいからです。
例えばマンタだけで考えれば、マンタの胴体(ルートになる)を中心に、各パーツの位置を調整すれば良いのですが、回転タイプではルートが回転軸になってしまうため、回転軸との相対位置では、マンタとしての構成パーツの位置が単純には合わないのです。
例えば、フリームーブタイプの場合のサイズ調整機能は以下のような感じになっています。
float f = 変更後の大きさ/変更前の大きさ; //体長の変更比率を求める。
llMessageLinked( LINK_SET, status, (string)f, NULL_KEY);
このリンクメッセージを受信して、変更比率からllSetScaleで大きさを変え、更にllSetPrimitiveParamsで位置を微調整しているのです。
link_message(integer sender_num, integer st, string msg, key id){
f = (float)msg;
llSetScale(llGetScale() * f);
llSetPrimitiveParams([PRIM_POSITION, llGetLocalPos() * f]);
}
ここで位置の微調整に使っているのがllGetLocalPos() です。つまりルートからの相対位置に対して、大きさ変更による比率を元に調整している訳です。
これが回転タイプだと使えなくなってしまうのですね。ルートが回転軸ですから、そこからの相対位置を元に調整したのではあわなくなってしまいます。あくまで、マンタ本体の中心を基準に調整しないと駄目ですからね。
回転方向を変えるに至ってはお手上げです。なにせ、マンタの向きを逆にしないといけません。すると、今まで右側にあったヒレは左側へ移動する事になります。尾びれも反対側に来ます。
回転の位置が苦手の方向音痴ゴンベとしては、こうなっては何が何やら?訳が分からずお手上げ状態です。
で、結局Sculpted Dolphins Shop方式で、ダイアログの設定内容を元に、次の手順で反映させる方式に至った訳ですね。
1.ダイアログで設定内容を入力
2.マンタ側にダイアログで設定した内容をパラメータで渡して、標準のマンタオブジェクトをRez
3.マンタ側はパラメータ内容を元に、サイズ調整と半径の位置へと移動
4.マンタと回転軸をリンク
5.回転開始
となる訳です。
そして、タッチして再設定したい時は、一旦マンタを消滅させて、再度Rezして反映させると言う事です。
しかし、これもけっこう面倒なスクリプトでした。
リンク設定・解除のパーミッションを取得したり、メッセージ交換でUUIDを受け取ったり、更に厄介なのは自爆時に回転軸を巻き込んで自爆してしまい、全てが消えてしまうとか・・・(T_T)ウルウル
時には、マンタの片翼だけ大きさが違うとか・・・(T_T)
とにかく焦りまくりでした。(^_^;)
この辺は、連続して命令を発すると、タイミングによっておかしな状態になってしまうようです。
そんな時に役に立つのが、毎度の事ながらSleep関数ですね。^ ^
例えば次のタッチでの自爆例を見てみましょう。
<ルート側>
link_message(integer sender_num, integer st, string msg, key id){
if(st == 9){
llBreakAllLinks();
}
}
<子側>
changed(integer change){
if (change & CHANGED_LINK) {
if(llGetLinkNumber()==0){
llSleep(1.0);
llDie();
}
}
}
これはタッチイベントで、停止ステータス(=9)を受け取り、リンク全解除している部分です。
親側でllBreakAllLinksを発動し、子側ではchangeイベントでリンク状態の変化を認識したら、1秒待って自爆させています。
当初はそのまま自爆させていたのですが、な・なんと!親だった回転軸プリムまで消滅してしまいました。
それで1秒待たせるようにした訳です。まあ、待たせなくても大丈夫な場合もあるのですが、どうもサーバの状態とかにもよるので、安定感を考えれば、1秒程度待つ心のゆとりが必要と言う事でしょう。
同じように、親プリムがマンタをRezした際にも、同じような工夫が必要でした。
親プリムからマンタがRezされた時に起動されるスクリプト部分は以下のようになります。
on_rez(integer param){
if(param>0){
key_id = llGetOwner();
size_no = (integer)llGetSubString((string)param, 0, 0)-1;
distance = (float)llGetSubString((string)param, 1, 2);
llSleep(1.0);
if(size_no!=1){
f = llList2Float(scale_p,size_no)/def_size;
llSetScale(llGetScale() * f);
llMessageLinked( LINK_SET, 20, (string)f, NULL_KEY);
}
llSetPos(llGetLocalPos()+<distance,0.0,0.0>);
llSay(chanel,llGetKey());
}
}
on_rezイベントで、受け取ったパラメータから、マンタのサイズと半径を切り出してます。
そして、1秒待って標準のMiddleサイズ以外が指定されていた場合は、サイズの変更比率を計算して、各パーツへとリンクメッセージを飛ばしている訳です。
そして、次に自分の位置を指定された半径の位置に移動させて、その後メッセージで自分のUUIDを親プリムに伝達しています。
親プリムは、このメッセージを受信すると、マンタをリンクして回転を始めると言う仕様です。
ここも、最初は1秒待たずにリンクメッセージを発してました。すると時々パーツの一部が大きさが変わらなかったりしていました。1秒待つようにしてからは、各パーツとも同期が合って、綺麗にサイズ調整がされるようになったと言う事です。
てな訳で、単純な回転タイプのオブジェクトですが、人様の使い勝手を考えて商品化するとなると、エライ面倒な事になるものです。
もし、自分だけが使うなり、設置場所が決まっているなら、単純なスクリプトで全く問題が無い訳ですからね。
もう一つ、この方式には問題があります。それはオーナーが編集権限を持っていないと、リンクの作成や解除がでいないのです。編集権限を持ったままで使用する事のリスクを検討しないといけないでしょう。
その辺も含めてもう少し調整したら、これらも販売開始したいと思いますが、正直言って「あまり安くはできないなー。。。」と言う感じですね。
うーん。止めようかな?
そんな時に役に立つのが、毎度の事ながらSleep関数ですね。^ ^
例えば次のタッチでの自爆例を見てみましょう。
<ルート側>
link_message(integer sender_num, integer st, string msg, key id){
if(st == 9){
llBreakAllLinks();
}
}
<子側>
changed(integer change){
if (change & CHANGED_LINK) {
if(llGetLinkNumber()==0){
llSleep(1.0);
llDie();
}
}
}
これはタッチイベントで、停止ステータス(=9)を受け取り、リンク全解除している部分です。
親側でllBreakAllLinksを発動し、子側ではchangeイベントでリンク状態の変化を認識したら、1秒待って自爆させています。
当初はそのまま自爆させていたのですが、な・なんと!親だった回転軸プリムまで消滅してしまいました。
それで1秒待たせるようにした訳です。まあ、待たせなくても大丈夫な場合もあるのですが、どうもサーバの状態とかにもよるので、安定感を考えれば、1秒程度待つ心のゆとりが必要と言う事でしょう。
同じように、親プリムがマンタをRezした際にも、同じような工夫が必要でした。
親プリムからマンタがRezされた時に起動されるスクリプト部分は以下のようになります。
on_rez(integer param){
if(param>0){
key_id = llGetOwner();
size_no = (integer)llGetSubString((string)param, 0, 0)-1;
distance = (float)llGetSubString((string)param, 1, 2);
llSleep(1.0);
if(size_no!=1){
f = llList2Float(scale_p,size_no)/def_size;
llSetScale(llGetScale() * f);
llMessageLinked( LINK_SET, 20, (string)f, NULL_KEY);
}
llSetPos(llGetLocalPos()+<distance,0.0,0.0>);
llSay(chanel,llGetKey());
}
}
on_rezイベントで、受け取ったパラメータから、マンタのサイズと半径を切り出してます。
そして、1秒待って標準のMiddleサイズ以外が指定されていた場合は、サイズの変更比率を計算して、各パーツへとリンクメッセージを飛ばしている訳です。
そして、次に自分の位置を指定された半径の位置に移動させて、その後メッセージで自分のUUIDを親プリムに伝達しています。
親プリムは、このメッセージを受信すると、マンタをリンクして回転を始めると言う仕様です。
ここも、最初は1秒待たずにリンクメッセージを発してました。すると時々パーツの一部が大きさが変わらなかったりしていました。1秒待つようにしてからは、各パーツとも同期が合って、綺麗にサイズ調整がされるようになったと言う事です。
てな訳で、単純な回転タイプのオブジェクトですが、人様の使い勝手を考えて商品化するとなると、エライ面倒な事になるものです。
もし、自分だけが使うなり、設置場所が決まっているなら、単純なスクリプトで全く問題が無い訳ですからね。
もう一つ、この方式には問題があります。それはオーナーが編集権限を持っていないと、リンクの作成や解除がでいないのです。編集権限を持ったままで使用する事のリスクを検討しないといけないでしょう。
その辺も含めてもう少し調整したら、これらも販売開始したいと思いますが、正直言って「あまり安くはできないなー。。。」と言う感じですね。
うーん。止めようかな?
llDetectedTouchST
llAddToLandPassList
【注意】Bulk Permissions機能は使っては駄目!
HTTP-INを使ってみた。
オブジェクトへの指示
ペットを作るには(6)
llAddToLandPassList
【注意】Bulk Permissions機能は使っては駄目!
HTTP-INを使ってみた。
オブジェクトへの指示
ペットを作るには(6)
Posted by Gonbe Shan at 19:59│Comments(0)
│スクリプトのお勉強メモ