Thyme

ThymeはPhunやAlgodooで使用されているスクリプト言語です。

Thymeスクリプトを使用すると、例えば、時間に合わせて引力の値が変化する図形を作ることができます。

目次

Thyme.cfgの内容

以下の文章は、Phunβ5.25に同梱されている、Thyme.cfgの内容を訳したものです(読みやすさのために、訳者の補足説明も地の文として表示しています)。

ThymeはAlgodooとPhunにおいて実装されている独自のスクリプト言語です。
基本となる型は4種類あります。Int型、Float型、Bool型、String型です。これらの型を組み合わせて、配列(リスト)や関数を作成することが可能です。
識別子は演算子 := を用いて宣言します。代入には = を使用してください。識別子は型付けされません。

hoge := 7; // 新しい識別子 'hoge' を初期値3で宣言します。
hoge = [hoge, "hello", true]; // 宣言済みの変数 'hoge' をリストとして再定義します。 このリストはヘテロジニアス(Heterogeneous:異種混合)です。
print hoge(1); // このコードは "hello" を返します。()で配列の要素にアクセスしています。
print hoge([0,2]); // このコードは [7, true] を返します。
isEven := (n)=>{ n%2==0 }; // 関数 "isEven" を宣言します。 1つの引数を受取、もし、その値が偶数ならtrueを返す関数です。


for関数が実装されています。
for関数は、Thymeにおけるシンプルなループ構造です。「再帰の上限」が存在する影響で、約50回以上ループさせると警告・もしくはエラーが出ます。
次のように使われます: for(n, (i)->{ ... }); ここで n は関数を呼ぶ回数です。 i は 0, 1, ..., n-2, n-1 受け取ります。
例:
for(4, (n)=>{print ((n+1) + " bottles of beer on the wall.")})
出力:
1 bottles of beer on the wall.
2 bottles of beer on the wall.
3 bottles of beer on the wall.
4 bottles of beer on the wall.

for関数は以下のように実装されています。
 for = (n, what)=>{
     n < 0 ? true : {
         for(n - 1, what);
         what(n-1)
     }
 };

他にも関数の定義例があります。
inclusive_range = (min, max)=>{min > max ? [] : {[min] ++ inclusive_range(min + 1, max)}};
infix 2 left: _ .. _ => inclusive_range; // Usage: 1..5 == [1,2,3,4,5]

infix は 演算子を定義します。これを定義しておくと、1..5 が [1,2,3,4,5]と同値になります。
infix 2 left は、結合の優先順位が2で、左結合という意味です。数が大きいほど優先順位が高く、演算子は強く結合します。

<- Thyme.cfgの内容ここまで。

Scene.my.~

シーンデータで使う独自の変数には
Scene.my.test := 1;
という具合に、先頭にScene.my.を付けて宣言します。
使用する際も、Scene.my.を付けます。

変数や関数を宣言する際に、Scene.my.を付けず、
test := 1;
などと定義してしまうと、testの定義がシーンファイルには保存されず、config.cfgに保存されてしまいます。

これには欠点が2つあります。
(欠点1)... 他人にシーンデータを渡しても上手く動作しない。
シーンデータに宣言した変数の情報がないため、Phunがシーンファイルを上手く解釈することができません。

(欠点2)... 管理が面倒。
config.cfgはPhunを起動する度に読み込まれる設定ファイルなので、config.cfgファイルを削除するかconfig.cfgを編集して該当箇所を取り除かない限り、宣言した変数の定義が残り続けてしまいます。逆に、config.cfgを消してしまうと、たとえシーンデータが残っていても、変数を宣言しなおす必要があります。
また、scene1.phz というシーンデータとscene2.phzで、同じ変数 test を使用していると、scene1.phzでtestの変数の値を迂闊に変更できないということになります。scene2.phzの挙動に影響するためです。

特に(欠点1)は忘れてはならない欠点です。
これらの欠点を理解し、通常は、シーンの変数にScene.my.~という識別子を使用するようにしましょう。

関数の宣言

関数は、
関数名 = (引数 [,引数2, 引数3, ...]) => {処理内容}
という形式で定義することができます。

絶対値を返す関数:
 Scene.my.abs = (x) => {x > 0 ? x : -x};
使用例:
 Scene.my.abs(-4)
出力
 4

値を整数に丸める関数(Int型に型変換を行うわけではありません)
 Scene.my.floor = (x) => {x >= 0 ? x - math.mod(x, 1) : (math.mod(x, 1) == 0 ? x : x - math.mod(x, 1) - 1)};
使用例:
 Scene.my.floor(3.14)
出力
 3

距離を返す関数:
 Scene.my.dist = (a, b)=>{((a(0) - b(0)) ^ 2 + (a(1) - b(1)) ^ 2)^0.5};
使用例:
 Scene.my.dist([0, 0], [3, 4])
出力:
 5

rand関数の実装例:
 Scene.my.next_rand = 1;
 Scene.my.rand = () => {Scene.my.next_rand = Scene.my.next_rand * 1103515245 + 12345; (Scene.my.next_rand / 65536) % 32768;};
 Scene.my.srand = (rand_seed) => {Scene.my.next_rand = Scene.my.rand_seed};
(このrand関数は、RAND_MAX := 32767 です。)
使用例:
 Scene.my.rand;
 Scene.my.rand;
出力
 16838
 -27009

衝突時に呼び出す関数の宣言(onCollide)

図形の衝突時に関数を呼び出すことも可能です。onCollideという属性を利用します。
 onCollide = (e)=>{処理したい内容}
という記述方法で、この処理内容の中では、衝突された図形および衝突した図形の属性の値を、
e.this.collideSet や e.other.color
で手に入れることができます。thisはスクリプトの書かれている図形、otherは衝突した図形です。
その他、e.posで衝突した位置を、e.normalで衝突した面の向きを得ることができます。

例えば、
 Scene.addBox{
   onCollide = (e)=>{Scene.addCircle{ radius := 0.1; collideSet := e.this.collideSet; pos := e.pos}}; 
 }
という図形(この場合はボックス)をPhunで作成すると、衝突する度に、衝突した位置に半径が0.1メートルで衝突グループが図形と同じ円(まる)が出る図形の完成です。※このスクリプトのままだと、物体が出続けてしまいます。

他に、
衝突するたびに色や密度の変化する図形
スコアボード
色の読み取り(Scene.my.で独自の変数recognitionを定義しています。)
などの例があります。
純粋なシミュレーションではなく、主にゲーム目的に広く応用できそうな機能と言えるかもしれません。

衝突した相手の物質のタイプを得る

公式フォーラムより。Iggyhopper氏の投稿内容です。
(e.other + "") で衝突した物体のタイプを判断することができます。
四角形→box
まる→circle
平面→plane
ポリゴン→polygon

使用例
(e) => { e.this.text = e.other + "" }
使用例2
(e) => { e.other +  "" == "box" ? {e.this.color = [0.5, 1, 0.5, 1]} : {e.this.color = [1, 1, 0.5, 1]} }

e.normalの解説

e.normalは衝突面の角度に対応したcosとsinを組み合わせた配列である。
以下のコードを利用することで角度(ラジアン)に変換することができる。

Scene.my.atan2 = (y, x)=>{ x == 0 ? { y > 0 ? {math.pi/2} : {-math.pi/2}} : { x > 0 ? {math.atan(y/x)} : { y > 0 ? {math.atan(y/x) + math.pi} : {math.atan(y/x) - math.pi}}}}
Scene.my.atan2(e.normal(1), e.normal(0))


このページの他、Thyme講座Thyme例文集Thyme実例集も参考になるかもしれません。

リファレンス

Gradyが使用できるコマンドをリストアップしてくれました(英語での説明付き)。

その他リファレンス

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2012年04月07日 10:38
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。