2009年01月08日
リスト変数応用 恋の話、略してk(ry
前回のリスト変数の使い方をまず読むこと。
それを使ってプチイベントで使えそうなものを作ってみた。

どっかで見たようなのが並んでるな。
こいつはタッチをすると、トークのお題がダダダーっと変わっていって、もう一度タッチをするとお題が決まる。
サイコロ転がすようなもんだが、サイコロと違うのは転がす場所を気にしなくていいことと、お題が6個じゃなくてもいいこと。
じゃあ中身の解説にいこう。
-----------------------------------------
list talk = ["恋の話", "困った話", "笑った話", "怒った話", "私の秘密"];
integer list_length;
integer list_num;
float timer_num;
string name;
default
{
state_entry()
{
list_length = llGetListLength(talk);
timer_num = 0.1;
integer i;
string title;
title = "お題は\n";
for(i = 0; i < list_length; i++)
{
title += llList2String(talk, i) + "\n";
}
llSetText(title, <1, 1, 1>, 1);
}
touch_start(integer total_number)
{
name = llDetectedName(0);
state start;
}
}
state start
{
state_entry()
{
llSetTimerEvent(timer_num);
}
touch_start(integer total_number)
{
state stop;
}
timer()
{
if(list_num == list_length)
{
list_num = 0;
}
llSetText(llList2String(talk, list_num), <1, 1, 1>, 1);
list_num++;
}
}
state stop
{
timer()
{
if(timer_num < 1.0)
{
timer_num += 0.2;
llSetTimerEvent(timer_num);
}
else
{
llSetTimerEvent(0.0);
llSay(0, name + "さんの選んだお話は " + llList2String(talk, list_num - 1) + "です!");
llSleep(5.0);
state default;
}
if(list_num == list_length)
{
list_num = 0;
}
llSetText(llList2String(talk, list_num), <1, 1, 1>, 1);
list_num++;
}
}
-----------------------------------------------
ちょっと頭をひねらないといけないところがあるぞ。
グローバル変数の種類は、上からお題リスト、リストの内容の数、その時選ばれている内容の番号、タイマーの秒数、タッチした人の名前。
まずはdefaultのstate_entryで初期設定。
integer llGetListLength(list src) は、リスト変数の内容の数を得る関数だ。
それを変数list_lengthに代入する。
注意が必要なのは、内容の数と内容の番号は違うということ。
今回は内容が5つあるけど、番号は0から始まるので、前から0、1、2、3、4という番号が振られている。
for(i = 0; i < list_length; i++) では、変数titleに内容を追加している。
繰り返し変数 i が内容の数より小さかったら繰り返すようにしているから、順番に内容を変数titleに追加していけるんだ。
この、リスト変数の内容の数を使ったfor文の使い方は基本なので、覚えて損はない。
最後に "\n" というのがあるけど、これは改行の意味。
キーボードでバックスラッシュを書くなら¥のキーを半角で打つ。
SL内では¥マークになる。
touch_startでタッチした人の名前を取得して、state start に移る。
state start では、タイマーでお題の表示を次々と切り替える。
timer イベントで if(list_num == list_length) の判定。
これは、今選ばれている内容が番号の一番最後かどうかを調べている。
混乱しないようにね。
リストの内容の番号は0から数えて、内容の数は1から数えるけど、繰り返し直前でlist_num++ をしている。
つまり、1回目は0、2回目は1、3回目は2、4回目は3、5回目は4、本来は内容がないはずの6回目で5になって、ここで内容の数の5と同じなる。
そこで内容表示前に0に戻すことで、無事にまた最初から繰り返しになるんだ。
だから内容の数と同じ数字で比較できるんだよ。
こればっかりは慣れて理解するしかない。
タッチをされると繰り返しを止めるためにstate stop に移る。
state stop では、ちょっと一工夫して、ドキドキ感を演出する。
パッと止めてもいいけど味気ないからね。
timerで if(timer_num < 1.0) の判定。
timer_num が1秒未満なら timer_num += 0.2 で0.2秒遅くする。
これで繰り返すたびに、どんどんタイマーが遅くなっていくわけ。
そして、タイマーが1秒以上になったら、llSetTimerEvent(0.0) でタイマーを止めてしまう。
llSay(0, name + "さんの選んだお話は " + llList2String(talk, list_num - 1) + "です!") で、最終的に止まった時の内容を発言しているわけだけど、ちょっと待った。
最後の方でlist_num++ で内容の番号に1を足している。
だからそのまま発言すると、番号が一つズレてしまうんだ。
そこでlist_num - 1 として1を引くことで1つ前に戻している。
んで5秒ほどウェイトを置いてstate default で一番最初に戻るわけだな。
このままだとテキスト表示だからプチイベント用しか使えないけど(遠くから見えないからね)、テクスチャで応用したら比較的大きい会場でも使えるかも知れない。
ただし何枚ものテクスチャを切り替えるのは少々重いので、1枚のテクスチャで切り替える工夫をしてみるといいね。
テクスチャの扱いに慣れてないと、ちょっと難しいと思うよ。
ちなみに、ステートをわざわざ切り替えているのはタッチ処理をするから。
ストップ動作中にまたタッチをされると困るんで、ステートを切り替えることでタッチをできなくさせているんだよ。
それを使ってプチイベントで使えそうなものを作ってみた。

どっかで見たようなのが並んでるな。
こいつはタッチをすると、トークのお題がダダダーっと変わっていって、もう一度タッチをするとお題が決まる。
サイコロ転がすようなもんだが、サイコロと違うのは転がす場所を気にしなくていいことと、お題が6個じゃなくてもいいこと。
じゃあ中身の解説にいこう。
-----------------------------------------
list talk = ["恋の話", "困った話", "笑った話", "怒った話", "私の秘密"];
integer list_length;
integer list_num;
float timer_num;
string name;
default
{
state_entry()
{
list_length = llGetListLength(talk);
timer_num = 0.1;
integer i;
string title;
title = "お題は\n";
for(i = 0; i < list_length; i++)
{
title += llList2String(talk, i) + "\n";
}
llSetText(title, <1, 1, 1>, 1);
}
touch_start(integer total_number)
{
name = llDetectedName(0);
state start;
}
}
state start
{
state_entry()
{
llSetTimerEvent(timer_num);
}
touch_start(integer total_number)
{
state stop;
}
timer()
{
if(list_num == list_length)
{
list_num = 0;
}
llSetText(llList2String(talk, list_num), <1, 1, 1>, 1);
list_num++;
}
}
state stop
{
timer()
{
if(timer_num < 1.0)
{
timer_num += 0.2;
llSetTimerEvent(timer_num);
}
else
{
llSetTimerEvent(0.0);
llSay(0, name + "さんの選んだお話は " + llList2String(talk, list_num - 1) + "です!");
llSleep(5.0);
state default;
}
if(list_num == list_length)
{
list_num = 0;
}
llSetText(llList2String(talk, list_num), <1, 1, 1>, 1);
list_num++;
}
}
-----------------------------------------------
ちょっと頭をひねらないといけないところがあるぞ。
グローバル変数の種類は、上からお題リスト、リストの内容の数、その時選ばれている内容の番号、タイマーの秒数、タッチした人の名前。
まずはdefaultのstate_entryで初期設定。
integer llGetListLength(list src) は、リスト変数の内容の数を得る関数だ。
それを変数list_lengthに代入する。
注意が必要なのは、内容の数と内容の番号は違うということ。
今回は内容が5つあるけど、番号は0から始まるので、前から0、1、2、3、4という番号が振られている。
for(i = 0; i < list_length; i++) では、変数titleに内容を追加している。
繰り返し変数 i が内容の数より小さかったら繰り返すようにしているから、順番に内容を変数titleに追加していけるんだ。
この、リスト変数の内容の数を使ったfor文の使い方は基本なので、覚えて損はない。
最後に "\n" というのがあるけど、これは改行の意味。
キーボードでバックスラッシュを書くなら¥のキーを半角で打つ。
SL内では¥マークになる。
touch_startでタッチした人の名前を取得して、state start に移る。
state start では、タイマーでお題の表示を次々と切り替える。
timer イベントで if(list_num == list_length) の判定。
これは、今選ばれている内容が番号の一番最後かどうかを調べている。
混乱しないようにね。
リストの内容の番号は0から数えて、内容の数は1から数えるけど、繰り返し直前でlist_num++ をしている。
つまり、1回目は0、2回目は1、3回目は2、4回目は3、5回目は4、本来は内容がないはずの6回目で5になって、ここで内容の数の5と同じなる。
そこで内容表示前に0に戻すことで、無事にまた最初から繰り返しになるんだ。
だから内容の数と同じ数字で比較できるんだよ。
こればっかりは慣れて理解するしかない。
タッチをされると繰り返しを止めるためにstate stop に移る。
state stop では、ちょっと一工夫して、ドキドキ感を演出する。
パッと止めてもいいけど味気ないからね。
timerで if(timer_num < 1.0) の判定。
timer_num が1秒未満なら timer_num += 0.2 で0.2秒遅くする。
これで繰り返すたびに、どんどんタイマーが遅くなっていくわけ。
そして、タイマーが1秒以上になったら、llSetTimerEvent(0.0) でタイマーを止めてしまう。
llSay(0, name + "さんの選んだお話は " + llList2String(talk, list_num - 1) + "です!") で、最終的に止まった時の内容を発言しているわけだけど、ちょっと待った。
最後の方でlist_num++ で内容の番号に1を足している。
だからそのまま発言すると、番号が一つズレてしまうんだ。
そこでlist_num - 1 として1を引くことで1つ前に戻している。
んで5秒ほどウェイトを置いてstate default で一番最初に戻るわけだな。
このままだとテキスト表示だからプチイベント用しか使えないけど(遠くから見えないからね)、テクスチャで応用したら比較的大きい会場でも使えるかも知れない。
ただし何枚ものテクスチャを切り替えるのは少々重いので、1枚のテクスチャで切り替える工夫をしてみるといいね。
テクスチャの扱いに慣れてないと、ちょっと難しいと思うよ。
ちなみに、ステートをわざわざ切り替えているのはタッチ処理をするから。
ストップ動作中にまたタッチをされると困るんで、ステートを切り替えることでタッチをできなくさせているんだよ。


