
今回はセンサースクリプトのお話です。
センサースクリプトとしては代表的な使い方のひとつで、
、持ってるいる人もいるかと思いますが、
HUD装着して他のアバターが何メートル先にいるかを教えてくれるスクリプトの紹介です。
ただ単に何メートル先かを知らせてくれるだけでは面白くないので、
後半では応用したものを載せておきます。
では、スクリプトから。
〜スクリプト〜
===================================================
1:float range=96.0; //Max96.0
2:float interval=2.0;
3:string str_av;
4:string str_name;
5:string str_dist;
6:default
7:{
8: state_entry()
9: {
10: llSensorRepeat("",NULL_KEY,AGENT,range,PI,interval);
11: }
12: sensor(integer num)
13: {
14: str_av="";
15: integer a;
16: for (a=0;a<num;a++)
17: {
18: vector my_pos=llGetPos();
19: vector dtc_pos=llDetectedPos(a);
20: //==============Avatar Name=====================
21: str_name=llDetectedName(a);
22: //==============================================
23: //===============Distance========================
24: str_dist=(string)llRound(llVecDist(dtc_pos,my_pos));
25: //===============================================
26: str_av=str_av+str_name+":"+str_dist+"m:\n";
27: }
28: llSetText(str_av,<1,1,1>,1);
29: }
30: no_sensor()
31: {
32: llSetText("",<1,1,1>,1);
33: }
34:}
===================================================
1行目や20行目にある「//」以降にある文字は注釈と言ってメモ書きみたいなものです。
スクリプトとしての機能はなく、覚書やメモを書いておくことができます。
メインとなるスクリプトは、
10行目、12行目、30行目の
llSensorRepeat("",NULL_KEY,AGENT,range,PI,interval);
sensor(integer num)
no_sensor()
です。
llSensorRepeatによってセンサーを起動することができます。
センサーを起動させてあと、
センサーに感知されたらsensor(integer num)以降のイベントが発生し、
何も感知されなかったらno_sensor()以降のイベントが発生します。
では、llSensorRepeatの中身ですが
llSensorRepeat(アバターやオブジェクトの名前,アバターやオブジェクトのID,感知する対象の種類,感知する範囲,感知する方向,感知する時間間隔);
となります。
アバターやオブジェクトの名前は、ここに名前を入れると、その名前だけに反応します。特定しない場合は””としておきます。
アバターやオブジェクトのIDは、UUIDをいれます。名前と同じく特定しない場合はNULL_IDとします。
感知する対象の種類は、4種類あって
・AGENT:アバター
・ACTIVE:移動しているオブジェクト
・PASSIVE:移動してないオブジェクト
・SCRIPTED:スクリプトが入っているオブジェクト
です。
感知する範囲は、何メートルまで感知するかを設定します(最大は96mです)。
感知する方向は、角度で表わします。感知する範囲が中心から何メートルと設定されますので、角度を最大にすると
ちょうど球形の感知エリアが生成されます。最大角度はラジアンで表わしPIとなります。
オブジェクトのX軸が角度の支軸になりますので、PI/2とすると、X軸を中心とした半球の形に感知エリアが形成されます。
感知する時間間隔は、何秒間隔にセンサーを起動するか設定します。
なので、
10行目の、llSensorRepeat("",NULL_KEY,AGENT,range,PI,interval)では
1行目〜2行目に
float range=96.0;
float interval=2.0;
と宣言していますので、
2秒間隔で、96mの中に入ってきたアバターを感知します。
センサーに感知されたら、12行目以降に移ります。
sensor(integer num)のnumは何個感知したかが代入されます。
1個感知されるとnumは0となりますので、10個感知だとnumは9となります。
18: vector my_pos=llGetPos();
19: vector dtc_pos=llDetectedPos(a);
20: //==============Avatar Name=====================
21: str_name=llDetectedName(a);
22: //==============================================
23: //===============Distance========================
24: str_dist=(string)llRound(llVecDist(dtc_pos,my_pos));
25: //===============================================
26: str_av=str_av+str_name+":"+str_dist+"m:\n";
感知されたものの名前を調べるには、
llDetectedName(a)
感知されたものの位置を調べるのは、
llDetectedPos(a)
です
(a)はinteger numに影響され、num(正確にはnum-1)個感知されたうちのa番目という意味です。
これで、名前と位置はわかりました。
自分と相手の距離を調べるのは簡単で、
24行目のllVecDist(dtc_pos,my_pos)です。
18行目で自分の位置(llGetPos())も調べてありますので
llVecDistですぐ算出されます。ただこのままでは、小数まで出てきますので
小数点以下を四捨五入させてllRound(llVecDist(dtc_pos,my_pos))としています。
アバター名:●●mと表示させたいので、26行目でstr_av+str_name+":"+str_dist+"m:\n"と表記させています。
この行の最後に\nとありますが、これは改行の意味です。
llSetTextでこの改行を表示させたい文字の中に入れると、2行・3行と行を分けることができます。
このllSetTextですが、
オブジェクトの上に文字を表示させるスクリプトです。
中身はllSetText(表示させたい文字,文字色,透明度)となっており
R,G,B,透明度は0〜1の数字を入れます。
ちなみに白は<1,1,1>、黒は<0,0,0>です。不透明は1、完全透明は0です。
一度llSetTextで文字をいれてしまうと、llSetTextの入ったスクリプトを消しても、オブジェクトの上の文字は消えません。
消したい場合は、llSetText("",<1,1,1>,1)のような空文字""をいれて消してくださいね。
〜応用編〜
基本的なセンサーの使い方の説明でしたが、これを応用して
相手がどっちの方向にいるか(自分から見て)のスクリプトを追加してみました。
アバター名:距離m:方向:上下
という風な表記にしています。
方向はForward,Back,Right,Leftの表記で8方向+同じXY軸上にいた時にCenter
上下はUp,Down+同じ高さにいた時にFlat
と表示させています。
===================================================
float range=96.0; //Max96.0
float interval=2.0;
string str_av;
string str_name;
string str_dist;
string str_dir;
string str_hi;
list list_dir=["Right","Forward/Right","Forward","Forward/Left","Left","Back/Left","Back","Back/Right","Right"];
default
{
state_entry()
{
llSensorRepeat("",NULL_KEY,AGENT,range,PI,interval);
}
sensor(integer num)
{
str_av="";
str_dir="";
str_hi="Flat";
integer a;
for (a=0;a<num;a++)
{
vector my_pos=llGetPos();
vector dtc_pos=llDetectedPos(a);
//==============Avatar Name=====================
str_name=llDetectedName(a);
//==============================================
//==============Height Level====================
float height=dtc_pos.z-my_pos.z;
if (height>=0.5)
{
str_hi="Up";
}
else
if (height<=-0.5)
{
str_hi="Down";
}
//===============================================
//===============Distance========================
str_dist=(string)llRound(llVecDist(dtc_pos,my_pos));
//===============================================
//===============Direction=======================
my_pos=;
dtc_pos=;
vector my_rot=llRot2Left(llGetRot());
vector dtc_rot=dtc_pos-my_pos;
float c=llAtan2(my_rot.x*dtc_rot.y-my_rot.y*dtc_rot.x,my_rot.x*dtc_rot.x+my_rot.y*dtc_rot.y);
str_dir=llList2String(list_dir,llRound(c/(PI/4))+4);
if (llVecDist(dtc_pos,my_pos)<1)
{
str_dir="Center";
}
//===============================================
str_av=str_av+str_name+":"+str_dist+"m:"+str_dir+":"+str_hi+"\n";
}
llSetText(str_av,<1,1,1>,1);
}
no_sensor()
{
llSetText("",<1,1,1>,1);
}
}
===================================================
追加した文は太文字で書いておきました。
このスクリプトの肝は、
float c=llAtan2(my_rot.x*dtc_rot.y-my_rot.y*dtc_rot.x,my_rot.x*dtc_rot.x+my_rot.y*dtc_rot.y);
です。
同一平面上の2ベクトル間の角度を求める式です。
自分の向いている方向をベクトル化し、自分と相手の位置をベクトル化させて、その間の角度を算出して、
相手が自分からみてどの方向にいるかを算出しています。
〜さて次回は〜
またまた、難しいことしてごめんなさい。。
もっと簡単なことできないかな〜っとお持てるのですが
では、次回はグレア(光)をスクリプトで制御してみます^^
====訂正====
Zexさんから、スクリプトのエラーがでるとのご指摘があったので
修正させていただきます。
どうも半角の<が入ってるとhtmlタグと勘違いされて、そのあとの文がところどころ消えてしまうみたい。。
ー修正箇所ー
16行目(応用編も同じところ)の
for (a=0;a<num;a++)
は、あえて全角<にしてました。(ここだけは文字消去されてしまったの気づいたのですが)
全角<を半角<に修正してください。
投稿者:メルティングドッツ|

