Gonbe Shan
2008年09月25日 10:38
integer handle;
vector target_pos;//移動目標地点の座標
vector now_locate;//移動範囲の基点座標
vector agent_pos;//ターゲットアバターの位置座標
integer status = 0;//現在の状態をあらわす。1=移動,9=停止
key key_id;
float strength = 1.0;//LookUp用の定数
float damping = 1.0;//同上
float tm = 2.0;//移動間隔(タイマー用)
float x_max;//移動範囲のMAX値(X座標方向)
float y_max;//移動範囲のMAX値(Y座標方向)
float x_min;//移動範囲のMIN値(X座標方向)
float y_min;//移動範囲のMIN値(Y座標方向)
list main_menu = ["Moving"];//ダイアログボタン
integer chanel=-9999;
integer target_flg;//ターゲットアバターが存在=1、無し=0
integer pos_rand(integer max, integer min){ // 乱数の発生。min~maxの範囲
return ((integer)llFrand(max-min)+min);
}
integer calc_target(vector pos,integer flg){//移動目標地点計算関数
if(flg==0){//ターゲットアバターが存在しない場合。
x_max=y_max=10.0;//基点から1m~10mの範囲内で移動
x_min=y_min=1.0;
}else{
x_max=y_max=1.0;//アバターから0.5m~1mの範囲内で移動
x_min=y_min=0.5;
}
float x_axi = pos_rand((integer)(x_max*10.0),(integer)(x_min*10.0))/10.0;
float y_axi = pos_rand((integer)(y_max*10.0),(integer)(y_min*10.0))/10.0;
target_pos = pos+<x_axi,y_axi,0.0>;//移動目標座標のセット
return (TRUE);
}
integer disp_menu(){//ダイアログ表示関数
llDialog(key_id, "\n<< Main Menu >>\n\n", main_menu, chanel);
return(TRUE);
}
default
{
state_entry()
{
key_id = llGetOwner();//オーナーのUUIDをセーブ
now_locate = llGetPos();//Rezポイントを基点へセット
state set_menu;
}
on_rez(integer param){
llResetScript();
}
}
state set_menu
{
state_entry()
{
llSetTimerEvent(0);//タイマーは停止
llSetPos(now_locate);//基点へ呼び戻し。
status = 9;
llMessageLinked( LINK_SET, status, "Stop", NULL_KEY);//各パーツへ停止を伝達
handle = llListen(chanel, "", key_id, "");ダイアログ用リッスンフィルタ
disp_menu();//ダイアログの表示
}
touch_start( integer total_number )
{
if(llDetectedKey(0)==key_id){
disp_menu();
}
}
listen(integer ch, string name, key id, string message){
if(message == "Moving"){
llListenRemove(handle);//リッスンの停止
status = 1;
llMessageLinked( LINK_SET, status, "Start", NULL_KEY);//各パーツへ活動開始を伝達
now_locate = llGetPos();//ボタンを押した地点を基点にセット
target_flg=0;
state moving;
}
}
on_rez(integer param){
llResetScript();
}
}
state moving
{
state_entry()
{
llSetTimerEvent(tm);//タイマー開始
llSensorRepeat("",NULL_KEY,AGENT,10.0,PI,3.0);//リピートセンサー開始。3秒間隔、10m以内のアバターを探知
}
touch_start( integer total_number )
{
if(llDetectedKey(0)==key_id){
llSensorRemove();
state set_menu;//オーナータッチでメニューへ
}
}
sensor(integer num_detected){
vector temp_pos = llDetectedPos(0);//見つかった一番目のアバターの位置
if(llVecDist(now_locate,temp_pos)<=10.0){//見つかったターゲットが、移動基点から10m以内なら追跡開始
if(target_flg==0){//ターゲット無しだった場合は
llSetTimerEvent(0);//タイマーは停止
target_flg=1;//ターゲットが存在
}
if(llVecDist(agent_pos,temp_pos)>1.0 ){//ターゲットが1m以上動いたら
vector agent_size = llGetAgentSize(llDetectedKey(0));//ターゲットの身長
agent_pos = <temp_pos.x,temp_pos.y,temp_pos.z+(agent_size.z/2)>;//ターゲットの高さを補正。ターゲットの中心位置に身長の半分を加算
}
calc_target(agent_pos,target_flg);//ターゲットアバターを中心に半径1m以内でランダムに移動
llSetPos(target_pos+<0.0,0.0,0.5>);//移動
llLookAt(agent_pos, strength, damping);//ターゲットの方向を向く
}else{
target_flg=0;//ターゲットが存在しなくなった
llSetTimerEvent(tm);//タイマー開始
}
}
no_sensor(){
if(target_flg==1){
target_flg=0;//ターゲットが存在しなくなった
llSetTimerEvent(tm);//タイマー開始
}
}
timer(){
calc_target(now_locate,target_flg);//移動目標自動計算
llLookAt(target_pos+<0.0,0.0,-0.5>, strength, damping);//移動目標を向く
llSetPos(target_pos);//移動
}
on_rez(integer param){
llResetScript();
}
}