2022/03/06

螺旋階段は時計回り?

 

西洋のお城の塔にある螺旋階段は登るとき時計回りが基本だそうです。
それは戦争のとき 攻め登る兵士は右手に持った剣を振るのに柱がじゃまになるけど 上から守る側の兵士は右手が自由に使えるので有利だから …。

その話をディスカバリーチャンネルか何かで見て 売ってるお城(参照: お城と岩のセット販売)を確認したら何も考えずに作ってたのでやっぱり逆回りでした。(><)

作ったときは半分に削ったトーラス(ドーナツ状のプリム)を引き伸ばして螺旋階段に見立ててましたが最近の何でもメッシュの世の中に迎合してついに階段だけメッシュ部品と入れ替えました。

すると部品は 1プリムでランドインパクトが 2 なのに大きさを変えるとランドインパクトが 3 になったりほかのプリムとリンクすると全体のランドインパクトがもっと増えるとか不思議なことが起こります。
もとのお城はプリムだけでできていて19プリム=19ランドインパクトですが 階段をメッシュ部品に入れ替えたら同じプリム数でもランドインパクトが 34になるのです!
…メッシュは謎です…。

ところで螺旋階段は本当に時計回りが多いか画像検索してみたら…逆回りもたくさんあります??
しかもお城の攻防で逆の説も出てきました:
螺旋階段のステップは扇型で柱側が狭く壁側が広いので兵士は足場を確保するため壁側に寄る そのとき攻め登る側は反時計回りの階段のほうが右手が壁に近くて自由が利かずに不利…。
…うーんどっちが正しいのか どっちも単なる都市伝説なのか…。

ちなみに lovemax の製品 MyCastle では いちいち階段を登らなくても柱にタッチ→メニューで行き先を選んでジャンプ で行けるので どっち回りか気にしなくてOK!

MyCastle はベネチアのお店の最上階から箱に乗って上空でデモを見ることができます。
あと 上空に行くと作りかけのベネチアの街も見ることができてベネチア SIM がどうやって作られているか雰囲気がなんとなくわかります。



2022/02/23

びっくり?宝箱

lovemax ワゴンの3番目アイテム: びっくり?宝箱 はもとの宝箱(参照: 金貨ぎっしり宝箱)に びっくり?機能を追加してさらに価格を 3分の1(!)まで下げた超お得な商品です。ベネチアカーニバル特設ワゴンセール限定。
…といってももとの価格はそもそもネタでつけた値段だったので その 3分の1もまたネタ価格。

ネタの話が出たので追加ネタを2つ。
ネタバレになって面白みが減ってはいけないので お買い上げしていただいた またはワゴンで確認していただいたお客さんのためだけに書くと:


追加ネタ1: ゼッキーニ金貨

ベネチア共和国で1284年からナポレオンに支配される1797年まで500年以上同じデザインで発行されていた金貨です。

写真は最後から2番目のドージェ(総督)パオロレニエの治世(1779-89年)中に作られた50ゼッキーニ金貨: 直径76mm 重さ192.5g
図柄はドージェが聖マルコに跪いています。(wikipedia ゼッキーノ/Sequin)


追加ネタ2: エトナ火山

イタリア南部シチリア島にある活火山です。

ヨーロッパ最大の活火山で 2018年の標高は3,326mですが活発な活動で高さはしょっちゅう変わるそうです。
アルプスを除いたイタリアでは最も高い山で2番目のヴェスヴィオ山の3倍近くもあります。
50万年前から頻繁に噴火を繰り返して 最近でもついおととい 2022年2月21日噴火があったようです。(wikipedia エトナ火山)

2022/02/21

特設ワゴンセール

ベネチア SIM のサンマルコ広場にはたくさんのセールスワゴンが並んでいます。
lovemax のワゴンで売ってるのは3つ:
  1. 肩乗り飛行船 (無料)
  2. 画像切り替え絵画 (L$ 55)
  3. びっくり?宝箱 (L$ 340)
2. 画像切り替え絵画 はベネチアの景観をたくさん描いた18世紀の画家カナレット(wikipedia カナレット/Giovanni Antonio Canal/1697-1768)の4枚の絵と昔のベネチアの地図が一定時間で切り替わります。

切り替え時間の設定は中のスクリプトを編集します。秒数などで指定できるほか h:時間, d:日, w:週, m:月, s:季節, y:年のように文字も使えます。

切り替えを日付から調べるスクリプト:

integer getCycleDate()
{ // return 年:2022-, 季節:1-4, 月:1-12, 0:それ以外
  if (Cycle=="") return 0;
  integer i = llSubStringIndex("msy",Cycle);
  if (i<0) return 0;
  string date = llGetDate(); // 日付: YYYY-MM-DD
  list info = llParseString2List(date,["-"],[]); // 年,月,日に分解
  if (i==2) return (integer)llList2String(info,0); // 年
  else {
    integer month = (integer)llList2String(info,1);
    if (i==0) return month; // 1-12月
    if (month==12) month = 0; // 12月を0に, 1-11月はそのまま
    return 1 + month / 3; // 季節; 1:冬-4:秋
  }
}

月,季節,年は毎日チェックしてそれ以外は指定した秒数または時間:h→60x60秒, 日:d→24x60x60秒, 週:w→7x24x60x60秒で切り替えます:

timer() {
  integer date = getCycleDate();
  if (date) { // 月,季節,年
    if (Date==date) return; // 前と同じなら何もしない
    else Date = date; // 違ってたら更新
  }
  setPicture(); // 絵を切り替える
}

2022/02/12

ベネチア SIM カーニバル

ベネチアSIMでカーニバルが始まりました。
期間は2022年2月12日(土)〜3月1日(火)でリアルのベネチアカーニバルと同じです。

カーニバル期間中は会場のサンマルコ広場でダンスや音楽イベントが何回もあり 広場には特設セールスワゴンがずらっと並びます。(lovemax も出店しています)

初日オープニングにはダンスイベントが開催されました。
広告看板を下げた飛行船も出動しました。(最近ではイベント恒例になってきました)

カーニバルという言葉(日本語では謝肉祭)はラテン語 carnem (肉を) levare (除く)がもとだそうで 断食をする四旬節が始まる灰の水曜日の前夜(なので最終日は火曜)に開かれた肉に別れを告げる祝宴だということです。(wikipedia 謝肉祭)

リアルのベネチアでは1162年から始まって 有名な仮面は 階級制度の厳しい時代でもカーニバルの間は仮面をかぶって違う階級や違う性別の服を着て 匿名のベネチア市民として自由な行動を満喫するのが流行したからだそうです。(wikipedia ヴェネツィア・カーニバル)

2022/02/05

2プリムでリンクの蓋を開閉

今までマーケットプレイスだけで売ってた宝箱を ベネチアのお店にも置くことにしたので この機会に今まで放置してた 2プリム蓋問題 を解決することにしました。

問題というのは 2プリムでできている宝箱の蓋をいっぺんに開閉するのに 今までは箱と蓋を別々のオブジェクトに(参照: リンクなしでも親子関係)してたのを 一つのオブジェクトでもできるようにする問題です。

千両箱と3億円ケース の蓋は よくあるドアと同じで 1プリムの箱の中心をヒンジにして削れば角度を変えるだけなのでわりと楽です。
でも宝箱の蓋は変形して削った箱(中心をヒンジに→角度だけでOK)と半分の円筒(中心をヒンジにはできない→角度も位置も変更)の組み合わせなのでちょっとめんどう。
なだけでなく角度を変えたり移動するスクリプト: llSetRot(), llSetPos() は 0.2秒停止するという謎なことが起こって そのままだと部品がバラバラに動くことになります。

解決策はスクリプトでも llSetLinkPrimitiveParamsFast() を使うことでした。
Fast と書いてあるだけに止まったりはしないんです!

こんな感じ:

list PrimPosLooks = [ // プリム名, 閉じたローカルの位置,向き, 開いた位置,向き
  "top", <-0.2, 0, 0.15>,<0,0,0>, <-0.2, 0, 0.15>,<0,-60,0>,
  "cap", <0, 0, 0.15>,<90,0,0>, <-0.1, 0, 0.32321>,<90,0,60>
]; // 位置:<x,y,z> メートル, 向き:<x,y,z> 度で表した回転

integer setPosRot(integer open)
{ // open:FALSE/0 →閉じる, TRUE/1 →開く
  string name = llGetObjectName(); // プリムの名前
  integer i = llListFindList(PrimPosLooks,[name]); //
  if (i<0 || LinkNumber<2) return -1; // もし何か間違ってたら脱出
  i = i+1 + open*2; // データの場所を計算
  vector pos = llList2Vector(PrimPosLooks,i); // 位置
  vector look = llList2Vector(PrimPosLooks,i+1); // 向き
  rotation rot = llEuler2Rot(look*DEG_TO_RAD); // 回転
  llSetLinkPrimitiveParamsFast(LinkNumber, // リンク番号
    [PRIM_POS_LOCAL,pos, PRIM_ROT_LOCAL,rot]); // 位置と回転
  return open;
}

宝箱はベネチア店の階段を上がった最上階 鉄格子の中にあります(といっても誰でも開けられる鉄格子なので雰囲気だけ)。

2022/01/30

簡単テレポの設定も簡単に

何年か前に作った簡単テレポ/ジャンプ(参照:階段を昇らずにジャンプ)ですが タッチだけでジャンプ先を設定するには 体の向きなどちょっとしたコツがいります。
それに離れた場所を設定するにはタッチは向いてません。(300メートル先まで設定はできるのですが…)

そこでプリムの説明のところに行先データを書いておけば それを読んで設定できるというスクリプトを書きました。

スクリプトの中に直接データを書くのは もし間違えたとき何が起こるかわからないので ちょっとどきどきですが それよりはずっと気楽に書けます。
説明に書き込むにはプリムの編集権限も必要なので 知らない間に誰かが間違って変えてしまう心配もないでしょう。

読む部分のスクリプトはこちら:

list getDestination(string data)
{ // data: " head : <pos.x, pos.y, pos.z>, look"
  // return [(string)head,(vector)pos,(float)look]
  integer i = llSubStringIndex(data,":"); // ":" がデータを書いてある印
  if (i<0) return [];
  string head = ""; // ":" が先頭(i==0)のとき頭は空
  if (0<i) head = llGetSubString(data,0,i-1); // ":" より前(頭)はデータ以外の説明に
  head = llStringTrim(head,STRING_TRIM); // 前後の空白は取っておく
  string body = llDeleteSubString(data,0,i); // ":" の後ろがデータ
  list info = llParseString2List(body,["<",">",","," "],[]); // 数字の書き方は気楽に
  vector pos = ZERO_VECTOR; // 行先の位置情報
  pos.x = (float)llList2String(info,0); // X座標(東西 メートル)
  pos.y = (float)llList2String(info,1); // Y(南北)
  pos.z = (float)llList2String(info,2); // Z(高さ)
  if (llVecMag(pos)<0.1) return []; // ほとんどゼロ座標だったら行先データではないはず
  float look = (float)llList2String(info,3); // 向き(角度 0度:東, 90度:北)
  return [head,pos,look];
}

写真の遊覧飛行船ドックでは案内看板と乗船デッキへの斜路に同じ仕組みを使ってます。
実際はもう少し複雑ですがそれは省略…(^^)

2022/01/22

繰り返しで説明文を表示

ベネチアSIMにはやはりというかいろんな国の方が来られます。

案内看板の説明が日本語だけだとなにか不親切な感じがします。
国際語の英語はもちろん ここはベネチアなのでイタリア語もほしいところ。
でもいっぺんに表示するとごちゃごちゃしてすっきりしないし 読みたいのは 3ヶ国語全部じゃなくひとつでいいはず。

というわけで 説明文を分けてそれを繰り返しで表示するスクリプトを作りました。
表示が次々変わるので 見た人の気を引く効果もありそうです。

スクリプトはこちら:

// Cycle Text v1.2
list Msgs = [
  "Tocca/Siediti al Porto del Dirigibile Turistico.",
  "Touch/Sit to Airship Sightseeing Port.",
  "タッチ/座って遊覧飛行船の出発地へ"];
float TimeCycle = 7; // 秒ごとに切り替え
integer Stride = 1; // 1度に表示する行数
integer Index = 0;

default {
  state_entry() {
    llSetText("",<1,1,1>,1);
    llSetTimerEvent(TimeCycle);
  }
  timer() {
    list lines = llList2List(Msgs,Index,Index+Stride-1); // 表示する文
    string text = llDumpList2String(lines,"\n"); // 2行以上なら改行でつなぐ
    llSetText(text,<1,1,1>,1); // テキスト表示
    Index += Stride; // 次の表示
    if (llList2String(Msgs,Index)=="") Index = 0; // 終わりなら先頭に戻る
  }
}

表示を1度に何行かまとめて出せるようにもしてあります。
Stride=1 になってますがこれを 2 にすれば2行づつ 4にすれば4行づつというわけです。