2008年03月23日
Avimator でつくる小島よしお
「ゼロから始める Avimator」では Avimator を使った静止ポーズの作り方を見てみましたが、今回はいよいよ動きのあるものに挑戦です。どうせつくるなら、面白いものをつくろうということで小島よしおを選ぶことにしました。「そんなの関係ねえ~、そんなの関係ねえ~、そんなの関係ねえ~、はいおっぱっぴ~」のくだりをアニメにしてみます。
いきなり小島よしお!? と思うかもしれませんが、実は簡単なんです。実際につくるのは3種類の静止ポーズだけです。
驚かれましたか? Avimator にはひとコマひとコマをつくらなくてもコマとコマの間の動きを補完してくれる機能があります。この機能を用いれば、静止ポーズを三つつくるだけであの小島よしおの動きをつくることができるのです。 では早速見ていきましょう。まず最初に全体のコマ数を330に設定してください。また、コマ送りのスピードは毎秒45コマにしてください。Avimator を開いて最初のひとコマ目はそのままにしておきます。これは前回も説明したように、最初のひとコマ目のポーズをリファレンスとしてそれ以降の動きを記録するからです。したがってひとコマ目はそのままにして、ふたコマ目に移動します。そしてこの二つ目のコマに最初のポーズをつくります。
最初のポーズは腕を上にあげた状態のポーズです。(下の写真)

データを以下に書いておきますので、この数値を体の各部位に入力してください。
head<0, -28, 0>, neck<0, 0, 0>, rCollar<0.02, 0, 0>, rshldr<0, 21, -21>, rForeArm<0, 127, -36>, rHand<0, 0, 21>, lCollar<0, -30, -26>, lShldr<0, 48, 24>, lForeArm<0, -145, -1>, lHand<-74, 0, -14>, chest<0, 54, 0>, abdomen<86, 0, 0>, hip<0, -85, 0>, rThigh<-38, 0, 0>, rShin<41, 0, 0>, rFoot<0, 0, 0>, lThigh<-63, 0, 0>, lShin<138, 0, 0>, lFoot<0, 0, 0>
ふたコマ目の静止ポーズができたら、今度はそのまま12コマ目に移動し、そこにまた別の静止ポーズをつくります。今度は腕を振り下ろして、足も後ろに向けて蹴りだしたポーズになります。(下の写真参照)

これもデータを以下に書きますので、この数値を12コマ目の体の各部位に入れてください。
head<0, -28, 0>, neck<0, 0, 0>, rCollar<0.21, 0, 0>, rshldr<0, 21, -21>, rForeArm<0, 127, -36>, rHand<0, 0, 21>, lCollar<0, -34, -26>, lShldr<6, -101, 4>, lForeArm<0, 8, -1>, lHand<-74, 0, -14>, chest<0, 46, 0>, abdomen<86, 0, 0>, hip<0, -85, 0>, rThigh<-38, 0, 0>, rShin<41, 0, 0>, rFoot<0, 0, 0>, lThigh<-2, 0, 0>, lShin<58, 0, 0>, lFoot<0, 0, 0>
このとき2コマ目と12コマ目の間のコマを見ると、ちょうどこの二つのコマのポーズの間をつなぐように体の各部位が動いているのがわかります。8コマ目の写真は下のような感じ。これが最初に述べた、コマとコマの間の動きを補完する機能です。

2コマ目の静止ポーズはコピーして、20コマごとにペーストしていきます。つまり、22、42、62、とペーストしていき、282コマまでペーストします。12コマ目のポーズも同様にしてこちらも20コマごとに32、52、72、とコピーペーストしていき、最後は292コマにコピーしておわりです。
以上で「そんなの関係ねえ~」の部分は終わりです。次に「おっぱっぴー」のポーズを作ります。
「おっぱっぴー」のポーズは293コマ目につくり、このポーズのまま最後の330コマ目までいきます。

「おっぱっぴー」ポーズのデータを以下に書いておきます。この数値を体の各部位に入力してください。
head<-34, 0, 7>, neck<0, 0, 0>, rCollar<0.13, 0, 0>, rshldr<0, 53, 52>, rForeArm<0, 114, 0>, rHand<0, 0, 0>, lCollar<0, 0, 22>, lShldr<0, 0, 23>, lForeArm<0, 0, 0>, lHand<0, 0, 0>, chest<0, 0, -7>, abdomen<22, 0, -14>, hip<0, 0, 0>, rThigh<62, 0, -54>, rShin<0, 0, 0>, rFoot<39, 0, 0>, lThigh<0, 0, 0>, lShin<0, 0, 0>, lFoot<0, 0, 0>
これで完了です。
なお、この小島よしおのアニメはわたしのお店 Jammie Jazzie Reggae Cafe/Second Mime Theater で Freebie として入手可能です。小島よしお以外にも読書アニメ付きAFKツールや、水玉ちょうちん袖のワンピースなども Freebie として置いてありますので、ぜひ一度お越しください。URLは以下です。
http://slurl.com/secondlife/kagurazaka%20japan/160/33/45
皆様のご来店をお待ちしております。
いきなり小島よしお!? と思うかもしれませんが、実は簡単なんです。実際につくるのは3種類の静止ポーズだけです。
驚かれましたか? Avimator にはひとコマひとコマをつくらなくてもコマとコマの間の動きを補完してくれる機能があります。この機能を用いれば、静止ポーズを三つつくるだけであの小島よしおの動きをつくることができるのです。 では早速見ていきましょう。まず最初に全体のコマ数を330に設定してください。また、コマ送りのスピードは毎秒45コマにしてください。Avimator を開いて最初のひとコマ目はそのままにしておきます。これは前回も説明したように、最初のひとコマ目のポーズをリファレンスとしてそれ以降の動きを記録するからです。したがってひとコマ目はそのままにして、ふたコマ目に移動します。そしてこの二つ目のコマに最初のポーズをつくります。
最初のポーズは腕を上にあげた状態のポーズです。(下の写真)

データを以下に書いておきますので、この数値を体の各部位に入力してください。
head<0, -28, 0>, neck<0, 0, 0>, rCollar<0.02, 0, 0>, rshldr<0, 21, -21>, rForeArm<0, 127, -36>, rHand<0, 0, 21>, lCollar<0, -30, -26>, lShldr<0, 48, 24>, lForeArm<0, -145, -1>, lHand<-74, 0, -14>, chest<0, 54, 0>, abdomen<86, 0, 0>, hip<0, -85, 0>, rThigh<-38, 0, 0>, rShin<41, 0, 0>, rFoot<0, 0, 0>, lThigh<-63, 0, 0>, lShin<138, 0, 0>, lFoot<0, 0, 0>
ふたコマ目の静止ポーズができたら、今度はそのまま12コマ目に移動し、そこにまた別の静止ポーズをつくります。今度は腕を振り下ろして、足も後ろに向けて蹴りだしたポーズになります。(下の写真参照)

これもデータを以下に書きますので、この数値を12コマ目の体の各部位に入れてください。
head<0, -28, 0>, neck<0, 0, 0>, rCollar<0.21, 0, 0>, rshldr<0, 21, -21>, rForeArm<0, 127, -36>, rHand<0, 0, 21>, lCollar<0, -34, -26>, lShldr<6, -101, 4>, lForeArm<0, 8, -1>, lHand<-74, 0, -14>, chest<0, 46, 0>, abdomen<86, 0, 0>, hip<0, -85, 0>, rThigh<-38, 0, 0>, rShin<41, 0, 0>, rFoot<0, 0, 0>, lThigh<-2, 0, 0>, lShin<58, 0, 0>, lFoot<0, 0, 0>
このとき2コマ目と12コマ目の間のコマを見ると、ちょうどこの二つのコマのポーズの間をつなぐように体の各部位が動いているのがわかります。8コマ目の写真は下のような感じ。これが最初に述べた、コマとコマの間の動きを補完する機能です。

2コマ目の静止ポーズはコピーして、20コマごとにペーストしていきます。つまり、22、42、62、とペーストしていき、282コマまでペーストします。12コマ目のポーズも同様にしてこちらも20コマごとに32、52、72、とコピーペーストしていき、最後は292コマにコピーしておわりです。
以上で「そんなの関係ねえ~」の部分は終わりです。次に「おっぱっぴー」のポーズを作ります。
「おっぱっぴー」のポーズは293コマ目につくり、このポーズのまま最後の330コマ目までいきます。

「おっぱっぴー」ポーズのデータを以下に書いておきます。この数値を体の各部位に入力してください。
head<-34, 0, 7>, neck<0, 0, 0>, rCollar<0.13, 0, 0>, rshldr<0, 53, 52>, rForeArm<0, 114, 0>, rHand<0, 0, 0>, lCollar<0, 0, 22>, lShldr<0, 0, 23>, lForeArm<0, 0, 0>, lHand<0, 0, 0>, chest<0, 0, -7>, abdomen<22, 0, -14>, hip<0, 0, 0>, rThigh<62, 0, -54>, rShin<0, 0, 0>, rFoot<39, 0, 0>, lThigh<0, 0, 0>, lShin<0, 0, 0>, lFoot<0, 0, 0>
これで完了です。
なお、この小島よしおのアニメはわたしのお店 Jammie Jazzie Reggae Cafe/Second Mime Theater で Freebie として入手可能です。小島よしお以外にも読書アニメ付きAFKツールや、水玉ちょうちん袖のワンピースなども Freebie として置いてありますので、ぜひ一度お越しください。URLは以下です。
http://slurl.com/secondlife/kagurazaka%20japan/160/33/45
皆様のご来店をお待ちしております。
2008年03月23日
ドアと窓を作ってみる(その2 - 窓編)
今回は窓をつくります。窓といってもただの窓ではありません。中が見えないようにカーテンをつけます。さらに、そのカーテンを開け閉めできるようにします。もちろん誰でも開けられるようでは困るので、特定の人しか開け閉めできないようなカーテンにします。
いままでは、サンプルスクリプトをそのまま入れてスクリプトを動かすことで、スクリプトを使う楽しさを体験してもらうことを狙いとしてきました。今回は一応設計めいたことに挑戦してみましょう。と言っても難しいことはありません。手順を追ってきちんとやっていけばだれにでもできます。
まず、「何をしたいのか(させたいのか)」を明確にしましょう。
そのために「なにをしなければいけないか」、もしくは「なくてはいけないか」もはっきりさせましょう。こういうこと5W1Hに従い「いつ、どこで、だれが、なにを、どうやって」実現するのか整理しておきます。
1)窓にカーテンをつける
いつ?>常に。どうやって?>カーテンのついた窓のテクスチャーを貼る。
2)カーテンを開ける
いつ?>窓にタッチしたとき。誰が?>特定のグループのメンバーが。どうやって?>テクスチャーを貼りかえる。
3)カーテンを閉める
いつ?>窓にタッチしたとき。誰が?>特定のグループのメンバーが。どうやって?>テクスチャーを貼りかえる。
4)特定の人だけカーテンを開けられる
いつ?>タッチしたとき。どうやって?>タッチした人がグループメンバーかどうか検知する。
前回のドアの時もそうでしたが、スクリプトには状態 (state) という概念があります。前回のドアの時はドアの開いた状態(state open) と閉まった状態(state close) がありました。また、それ以外に実際のスクリプト上では初期設定を行う default という状態もありました。今回もカーテンの開いた状態と閉まった状態がありますので状態(state)に関してはドアの時と同じです。今回はdefault の状態をカーテンの閉まった状態(close) と考え、default と state open の二つの状態(state)でスクリプトを作ってみたいと思います。
スクリプトを書いていくときに、最初の状態(state) は必ず default が使われます。この default という状態(state)の中でやってもらいたいことをスクリプトを使って書いていきます。やってもらいたいことはさっき書き出したとおりですね。まずは(1)窓にカーテンをつける=カーテンのついた窓のテクスチャーをプリムに貼って窓をつくる。でしたね。今回使うテクスチャーはカーテンが閉まった状態の窓とカーテンが開いた状態の窓、それを内側と外側それぞれ作ります。合計4枚のテクスチャーが必要になるということです。まず、カーテンの閉じた状態の窓のテクスチャーを貼ることにしましょう。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartaincloseout", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainclosein", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
}
"cartaincloseout" が閉じたカーテンのテクスチャー外側、"cartainclosein" が閉じたカーテンのテクスチャー内側です。"Brazillian rosewood" というのは窓枠の部分に貼ったテクスチャーです。SLを始めた時に初期でついてきたテクスチャーの中にありますが、ここはそれぞれ好みで色んなテクスチャーを選んでください。上記スクリプトと、スクリプトの中で指定したテクスチャーをオブジェクトのコンテンツの中に入れると、下の写真のように窓の体裁をなすようになります。
わかりやすいようにコピーして、窓の内側と外側が見えるようにしました。

次にカーテンの開いた状態の窓を作ってみることにしましょう。作り方はカーテンの閉じた状態の窓と全く同じです。
ただし、テクスチャーだけが窓の開いた状態のものに変わります。今回は "cartainopenout" と "cartainopenin" という名前になっています。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartainopenout", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainopenin", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
}
下の写真をご覧ください。ちゃんとカーテンが開いて窓の向こうの景色が見えますね。わかりやすいようにカーテンを閉めた状態のものと並べてみました。

あとはこの二つの状態をいったりきたりできるようにすればいいわけです。最初に5W1Hで整理したように、タッチしたときに切り替わるようにしたいんでした。そこで窓にタッチしたときに二つの状態を行ったり来たりできるようなスクリプトを追加します。開閉二つの状態と、その間を窓にタッチするたび行ったり来たりできるスクリプトは下記のようになります。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartaincloseout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainclosein", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
state open;
}
}
state open
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartainopenout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainopenin", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
state default;
}
}
見ていただくとわかるとおり、カーテンが閉まった状態(default)の方は touch_start(integer total_number) という部分とstate open; という部分が追加されました。これは「タッチしたときに、state open という状態(state)に移行するということを意味しています。同様にしてカーテンが開いた方の状態(state open)の方も、touch_start(integer total_number) と、こちらは state default; という記述があります。これも同様に「タッチしたときにstate default(つまりカーテンの閉まった状態)に移行しますということです。
上記スクリプトと4種類のテクスチャー(窓の開閉x内と外)を窓のプリム(オブジェク)のコンテンツに入れて家にとりつけてみました。それが下の写真です。

タッチするとちゃんとカーテンが開いて部屋の中が見えます。当然部屋からもカーテンを開けて外を見ることができます。

最後の仕上げはセキュリティーですね。タッチしたときにグループメンバー以外はカーテンを操作できないようにします。
グループメンバーかどうかを検知するには llDetectedGroup(0) という機能を使います。この機能を用いて条件文をつくり、グループメンバーであればカーテンが開き(閉じ)、グループメンバーでない場合は"You are not granted to touch" というメッセージが出るようにします。これを行うために以下の記述を touch_start(integer total_number) に続けて加えます。
touch_start(integer total_number)
{
if(llDetectedGroup(0);)
{
state open; ((閉める場合は state defualt; )
}
else
{
llSay(0, "You are not granted to touch");
}
これを入れて完成させたスクリプトが下記のものです。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartaincloseout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainclosein", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
if(llDetectedGroup(0))
{
state open;
}
else
{
llSay(0, "You are not granted to touch");
}
}
}
state open
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartainopenout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainopenin", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
if(llDetectedGroup(0))
{
state default;
}
else
{
llSay(0, "You are not granted to touch");
}
}}
スクリプト全般に言えることですが、中で使われている括弧( { や } )の数に気をつけてください。
ちゃんと正しい場所に使われているか。もしくは前の括弧と後の括弧の数が合っているかなどです。実際にスクリプトを書くときには In World (SL内)でエディターを使って書いていきますので、括弧に限らず誤りがあると保存するときにエラーが出て知らせてくれます。よくある文法エラーとしてはこの括弧の間違いや、セミコロンのつけ忘れ、もしくはいらないところにつけてる、などがあります。この辺は習うより慣れろで実際に使っているうちに誤りも少なくなってくるでしょう。
長い記事でしたが、ようやく終了です。グループ限定のセキュリティーの方もちゃんと動いてくれました。(下写真)

家づくりが一段落したので、今度は久しぶりに Avimatar で遊んでみましょう。前回は静止ポーズでしたが、次は動きのあるものに挑戦です。題材としては、もはや旬は過ぎた感は否めませんが小島よしおですw お楽しみに。
いままでは、サンプルスクリプトをそのまま入れてスクリプトを動かすことで、スクリプトを使う楽しさを体験してもらうことを狙いとしてきました。今回は一応設計めいたことに挑戦してみましょう。と言っても難しいことはありません。手順を追ってきちんとやっていけばだれにでもできます。
まず、「何をしたいのか(させたいのか)」を明確にしましょう。
そのために「なにをしなければいけないか」、もしくは「なくてはいけないか」もはっきりさせましょう。こういうこと5W1Hに従い「いつ、どこで、だれが、なにを、どうやって」実現するのか整理しておきます。
1)窓にカーテンをつける
いつ?>常に。どうやって?>カーテンのついた窓のテクスチャーを貼る。
2)カーテンを開ける
いつ?>窓にタッチしたとき。誰が?>特定のグループのメンバーが。どうやって?>テクスチャーを貼りかえる。
3)カーテンを閉める
いつ?>窓にタッチしたとき。誰が?>特定のグループのメンバーが。どうやって?>テクスチャーを貼りかえる。
4)特定の人だけカーテンを開けられる
いつ?>タッチしたとき。どうやって?>タッチした人がグループメンバーかどうか検知する。
前回のドアの時もそうでしたが、スクリプトには状態 (state) という概念があります。前回のドアの時はドアの開いた状態(state open) と閉まった状態(state close) がありました。また、それ以外に実際のスクリプト上では初期設定を行う default という状態もありました。今回もカーテンの開いた状態と閉まった状態がありますので状態(state)に関してはドアの時と同じです。今回はdefault の状態をカーテンの閉まった状態(close) と考え、default と state open の二つの状態(state)でスクリプトを作ってみたいと思います。
スクリプトを書いていくときに、最初の状態(state) は必ず default が使われます。この default という状態(state)の中でやってもらいたいことをスクリプトを使って書いていきます。やってもらいたいことはさっき書き出したとおりですね。まずは(1)窓にカーテンをつける=カーテンのついた窓のテクスチャーをプリムに貼って窓をつくる。でしたね。今回使うテクスチャーはカーテンが閉まった状態の窓とカーテンが開いた状態の窓、それを内側と外側それぞれ作ります。合計4枚のテクスチャーが必要になるということです。まず、カーテンの閉じた状態の窓のテクスチャーを貼ることにしましょう。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartaincloseout", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainclosein", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
}
"cartaincloseout" が閉じたカーテンのテクスチャー外側、"cartainclosein" が閉じたカーテンのテクスチャー内側です。"Brazillian rosewood" というのは窓枠の部分に貼ったテクスチャーです。SLを始めた時に初期でついてきたテクスチャーの中にありますが、ここはそれぞれ好みで色んなテクスチャーを選んでください。上記スクリプトと、スクリプトの中で指定したテクスチャーをオブジェクトのコンテンツの中に入れると、下の写真のように窓の体裁をなすようになります。
わかりやすいようにコピーして、窓の内側と外側が見えるようにしました。

次にカーテンの開いた状態の窓を作ってみることにしましょう。作り方はカーテンの閉じた状態の窓と全く同じです。
ただし、テクスチャーだけが窓の開いた状態のものに変わります。今回は "cartainopenout" と "cartainopenin" という名前になっています。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartainopenout", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainopenin", <1, 1, 0>, <0, 0, 0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
}
下の写真をご覧ください。ちゃんとカーテンが開いて窓の向こうの景色が見えますね。わかりやすいようにカーテンを閉めた状態のものと並べてみました。

あとはこの二つの状態をいったりきたりできるようにすればいいわけです。最初に5W1Hで整理したように、タッチしたときに切り替わるようにしたいんでした。そこで窓にタッチしたときに二つの状態を行ったり来たりできるようなスクリプトを追加します。開閉二つの状態と、その間を窓にタッチするたび行ったり来たりできるスクリプトは下記のようになります。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartaincloseout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainclosein", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
state open;
}
}
state open
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartainopenout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainopenin", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
state default;
}
}
見ていただくとわかるとおり、カーテンが閉まった状態(default)の方は touch_start(integer total_number) という部分とstate open; という部分が追加されました。これは「タッチしたときに、state open という状態(state)に移行するということを意味しています。同様にしてカーテンが開いた方の状態(state open)の方も、touch_start(integer total_number) と、こちらは state default; という記述があります。これも同様に「タッチしたときにstate default(つまりカーテンの閉まった状態)に移行しますということです。
上記スクリプトと4種類のテクスチャー(窓の開閉x内と外)を窓のプリム(オブジェク)のコンテンツに入れて家にとりつけてみました。それが下の写真です。

タッチするとちゃんとカーテンが開いて部屋の中が見えます。当然部屋からもカーテンを開けて外を見ることができます。

最後の仕上げはセキュリティーですね。タッチしたときにグループメンバー以外はカーテンを操作できないようにします。
グループメンバーかどうかを検知するには llDetectedGroup(0) という機能を使います。この機能を用いて条件文をつくり、グループメンバーであればカーテンが開き(閉じ)、グループメンバーでない場合は"You are not granted to touch" というメッセージが出るようにします。これを行うために以下の記述を touch_start(integer total_number) に続けて加えます。
touch_start(integer total_number)
{
if(llDetectedGroup(0);)
{
state open; ((閉める場合は state defualt; )
}
else
{
llSay(0, "You are not granted to touch");
}
これを入れて完成させたスクリプトが下記のものです。
default
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartaincloseout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainclosein", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
if(llDetectedGroup(0))
{
state open;
}
else
{
llSay(0, "You are not granted to touch");
}
}
}
state open
{
state_entry()
{
llSetPrimitiveParams([PRIM_TEXTURE, 1, "cartainopenout", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 3, "cartainopenin", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0]);
llSetPrimitiveParams([PRIM_TEXTURE, 0, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 2, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 4, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
llSetPrimitiveParams([PRIM_TEXTURE, 5, "Brazillian rosewood", <1,1,0>, <0,0,0>, 0]);
}
touch_start(integer total_number)
{
if(llDetectedGroup(0))
{
state default;
}
else
{
llSay(0, "You are not granted to touch");
}
}}
スクリプト全般に言えることですが、中で使われている括弧( { や } )の数に気をつけてください。
ちゃんと正しい場所に使われているか。もしくは前の括弧と後の括弧の数が合っているかなどです。実際にスクリプトを書くときには In World (SL内)でエディターを使って書いていきますので、括弧に限らず誤りがあると保存するときにエラーが出て知らせてくれます。よくある文法エラーとしてはこの括弧の間違いや、セミコロンのつけ忘れ、もしくはいらないところにつけてる、などがあります。この辺は習うより慣れろで実際に使っているうちに誤りも少なくなってくるでしょう。
長い記事でしたが、ようやく終了です。グループ限定のセキュリティーの方もちゃんと動いてくれました。(下写真)

家づくりが一段落したので、今度は久しぶりに Avimatar で遊んでみましょう。前回は静止ポーズでしたが、次は動きのあるものに挑戦です。題材としては、もはや旬は過ぎた感は否めませんが小島よしおですw お楽しみに。