2009年09月29日

時間でテクスチャを切り替える

こんにちは。

今、アイテムキャンプのスクリプトをいじっているのですが、フローティングテキストが嫌でテクスチャの表示にしたいと考えています。
0123456789のテクスチャ(数字1個につき1枚)を作ったのですが、それを残り時間に応じて表示したいのです。
数字にテクスチャを当てはめる方法がわかりません。
※設定できる時刻は1分~最大99分です。

スクリプトそのものではなくて、参考やヒントでも構いませんので、ご教授いただけると助かります。
なにとぞよろしくお願いします。

※現在作っているテクスチャは数字1個につき1枚ですが、まだ未アップなので0-9で1枚のテクスチャに変更も可能です。
 テクスチャのアップ代を考えるとそちらの方がいいとは思うのですが、テクスチャをずらすのが苦手で1枚1枚にしてみました。



同じカテゴリー(スクリプト関連)の記事画像
オブジェクトのリンクとタッチで開く扉
自動チャットを止めたい
テレポートするとアニメーションが解除される
同じカテゴリー(スクリプト関連)の記事
 テクスチェンジのHUDについて (2015-07-01 04:51)
 モール用のプリムカウンターを探しています (2014-11-29 20:09)
 連続するアニメーションの処理 (2014-08-24 03:23)
 オブジェクトの上にフローティングテキストを出す。 (2014-08-22 16:46)
 チャットログの盗聴について (2014-02-03 03:43)
 椅子に座った後で位置調整できるスクリプト (2013-03-24 16:37)

Posted by LoveHeart  at 12:58 │Comments(7)スクリプト関連

この記事へのコメント
リンクプリムに時間表示させるということでいいんでしょうか?
それと、設定する時間は1桁でいいんですかね?(9分以内?)

アイテムキャンプということなので、llSetTimerEvent()で1分経過したら残り時間を1減らしてllSetText()で表示する、みたいな処理がしてあるともうのですがtimer()イベント内で

llSetText("残り時間は" + time, <1.0, 1.0, 1.0>, 1.0);

こんな感じになってたら、このtimeに該当するテクスチャをllSetLinkTexture()でリンクプリムに表示すればいいですよね。


テクスチャを10枚にするなら、テクスチャの名前を”0”、”1”、”2”・・・にしておくと

llSetLinkTexture(2, (string)time, 0); //パラメータは左からリンク番号, テクスチャ名, 表示する面

とできます。


テクスチャを1枚にする場合は、テクスチャの繰り返しとずれを指定してやる必要があります。
編集ツールのテクスチャのとこにありますよね。あれをスクリプトで変更します。
llSetLinkTexture()ではできないので、llSetLinkPrimitiveParams()を使います。

llSetLinkPrimitiveParams(integer linknumber, [PRIM_TEXTURE, integer face, string texture, vector repeats, vector offsets, float rotation_in_radians])

repeats, offsets が繰り返しとずれです。

repeats は、テクスチャを縦横それぞれ何回繰り返して表示するを、vectorのxとyで指定します。
普通ににテクスチャを貼っただけだと、縦・横とも1になってます。vectorで表すと<1.0, 1.0, 0.0> (xが横、yが縦 zは無視されます)

"0"~"9"の数字を左から右へ一列に並べだテクスチャを作ったとして考えると、
縦は1.0のままでいいですよね。横は全体の1/10を表示したいので0.1です。
つまり repeats = <1.0, 0.1, 0.0>
これはどの数字を表示する場合も一緒になります。

offsetsは、テクスチャを中心からどれだけずらして表示するかです。
プリムの面の中心を縦横それぞれ0として表します。全体が1なので、最小が-0.5、最大が0.5です。これもvectorのxとyで指定します。
テクスチャの一番左上を面の中心に持ってくるなら offsets = <-0.5, 0.5, 0.0>
一番右下を中心にするなら offsets = <0.5, -0.5, 0.0>
という具合です。
デフォルトではテクスチャの中心がプリムの面の中心と一緒になってますのでoffsets = <0.0, 0.0, 0.0>ですね。ここからどれだけずらせば目的の数字を表示できるか考えると、
yは0.0で固定でいいですよね。
xは、一文字分ずらすためには0.1足すか引くかすればいいことになります。
x=0.0は"4"と"5"の間になりますから、x=0.05にすれば"5"の中心が面の中心になって、面全体に”5”が表示されます。x=-0.05なら”4”ですね。”6”は”5”から右へ0.1ずらせばいいからx=0.15です。
"0"  offsets = <-0.45, 0.0, 0.0>
"1"  offsets = <-0.35, 0.0, 0.0>
"2"  offsets = <-0.25, 0.0, 0.0>
 ・
 ・
"9"  offsets = <0.45, 0.0, 0.0>


なので、timer()イベントでtimeが得られたら、

float x= -0.45 + time/10; //”0”のとき-0.45で、timeが1増えるごとに0.1増える
llSetLinkPrimitiveParams(2, [PRIM_TEXTURE, 0, "numbers", <1.0, 0.1, 0.0>, <x, 0.0, 0.0>, 0.0]);



キャンプに設定する時間は1桁として書きましたので、10以上設定したい場合はリンクプリムを2つにして1の位と10の位に分けて処理するか、10以上の数も含めてテクスチャを作って対応するとかしないといけません。
Posted by あ at 2009年09月29日 18:55
>あ さん
ありがとうございます。

0-9の数字を使うので2桁なのです。
最大99分まで出来るように作っているので…。

プリムをカットして面を作り、そこに表示するつもりでした。
親プリムからLinkMessageで子プリムがメッセージを受けて表示する形にしようとしています。
テクスチャ自体は0-9で1枚のものを最初から貼っておいてオフセットでずらす方法が簡単なのかな、とも思っています。

残り時間とテクスチャの関連付けがいまいちわかっていないかもしれません。
もし2桁以上であれば今のまとめて計算している方法だと出来ないということがわかったので、10の位と1の位を分けて処理する方法を探ってみたいと思います。

ありがとう御座いました。
Posted by LoveHeartLoveHeart at 2009年09月29日 19:37
ちなみにこのようになっています。

//時間を得る
string getTime(integer timeleft) {
if (timeleft<0) return "00:00";
integer hour=timeleft/ 3600;
integer minute=(timeleft % 3600) / 60;
integer second=timeleft % 60;
string time="";
if(hours>9) time += (string)hour + ":"; else if(hour>0) time += "0" + (string)hour + ":";
if(minutes>9) time += (string)minute + ":"; else time += "0" + (string)minute + ":";
if(seconds>9) time += (string)second; else times += "0" + (string)second;
return time + " Time left";
}

//タイマーで更新
timer(){
integer NOWTIME = llGetUnixTime();
integer TIMELEFT = REMTIME - (NOWTIME - SETTIME);
llSetText(getTime(TIMELEFT),<1.0,1.0,1.0>,1.0);
//
if (TIMELEFT < 0) llSetTimerEvent(0.0);
}

timerの前にリンクメッセージで受けたものを処理していますが、割愛しました。

時間の設定は汎用ではなく自分用なのでオブジェクトの説明欄に秒数を書いてそれを参照しに行くようにしています。
Posted by LoveHeart at 2009年09月29日 20:00
スクリプトを拝見したところ、変数TIMELEFTに残り時間を秒数で代入して、それを「○○:○○:○○」(○○時間○○分○○秒)といった形の文字列に変換してテキスト表示しているようですね。
>最大99分まで出来るように
ということなので、今回の場合分数2桁でテクスチャ表示したいということだと思います。
秒までテキスト表示するためにタイマーは1秒間隔になっていると思いますが、1分間隔でよいでしょう。
llSetTimerEvent(60);


timer(){
integer NOWTIME = llGetUnixTime();
integer TIMELEFT = REMTIME - (NOWTIME - SETTIME); //REMTIME: キャンプする秒数 SETTIME: キャンプ開始したUNIXTIME?
if (TIMELEFT<0){
llSetTimerEvent(0.0);
// ここに設定時間が経過したときの処理が入る
return; // キャンプしていない状態に戻る。
}

integer minute=TIMELEFT/ 60; // TIMELEFTを秒から分に変換
integer upper = minute/10; // 10の位
integer lower = minute - upper; // 1の位

float x= -0.45 + upper/10; // 10の位の表示
llSetLinkPrimitiveParams(2, [PRIM_TEXTURE, 5, "numbers", <1.0, 0.1, 0.0>, <x, 0.0, 0.0>, 0.0]);

x= -0.45 + lower/10; // 1の位の表示
llSetLinkPrimitiveParams(2, [PRIM_TEXTURE, 6, "numbers", <1.0, 0.1, 0.0>, <x, 0.0, 0.0>, 0.0]);
}


こんな感じになるんじゃないでしょうか。
(パスカットしたときの面番号がどうなるか忘れてしまったので、とりあえず5と6で書きました。offsetなどもパスカットの場合変わるかもしれません。)
Posted by あ at 2009年09月30日 01:07
ごめんなさい
integer lower = minute - upper*10;
でした
Posted by あ at 2009年09月30日 01:15
ちょっと思い出したことがあって調べてみました。
http://wiki.secondlife.com/wiki/XyText_1.5

1プリムで英数字10文字まで表示できるものです。これを使うと、getTime()関数で取得した文字列をそのまま表示できそうです。テクスチャもあらかじめ用意されてるので、新たにUPする必要もありません。


使い方は、
1.まず何でも良いのでオブジェクトをひとつRezし、その中に上記ページの一番上の”XyText v1.0.3 Prim Setup Script”を入れます。
するとオブジェクトの形が変わってスクリプトは消えます。

2.オブジェクトに二番目のスクリプト”XyText v1.0.3 Script”を入れます。

3.アイテムキャンプのオブジェクトに子プリムとしてリンクします。

4.ページ一番したの”Example Use”のようにルートプリム側からリンクメッセージを送ると、送った文字列が子プリムに表示されます。


llMessageLinked(LINK_SET, 204000, getTime(TIMELEFT), "");

とすれば、”TIMELEFT”がそのまま子プリムに表示されるはずです。
Posted by あ at 2009年09月30日 10:37
>あ さん
Wikiに載っていたのですね、Wikiは見ていたのですが見落としていました。

試してみたところ、こちらで問題なく表示されました。
本当にありがとうございます。
Posted by LoveHeart at 2009年09月30日 14:40
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。