Thyme講座

「Thyme講座」の編集履歴(バックアップ)一覧はこちら

Thyme講座」(2012/03/26 (月) 21:36:52) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

#contents(,option=word) *&bold(){Thyme講座} Thymeは初心者やプログラム経験のない方にとってはハードルが高い。思いつきではあるが、ここにThyme講座を書きなぐっていきたいと思う。&br; 尚思いつきかつ、筆者も独学にちかい部分があるため、不明瞭な部分や間違い等があると予想される。&br; そのような部分を発見した場合、コメントにて指摘いただけるとありがたい。&br; &br; *なにはともあれ書き方と例文 まずスクリプトがどのようなものなのか、見ていただこう。&br; &br; 物質のテキスト文章部分にシミュレーション開始からの経過時間を表示させるスクリプト e.onCollide = (e) => {   text = { "" + sim.time }; } &br; 常に物質の色を変え続けるスクリプト e.onCollide = (e) => {   color = { [ sim.time % 1.0 , sim.time * 0.5 % 1.0 , sim.time * 0.3 % 1.0 , 1.0 ] }; }  このような1処理分の塊を「式」という。&br; 式1つは「○○○ = ○○○」の形をとる。  ただし、スクリプトメニューをよく見ると「e.onCollide = 」はすでに記述されていて、その中身が「(e)=>{}」となっている。&br; つまり実際に使用する場合は onCollide内の状態を「(e)=>{ text = {"" + sim.time}; }」とすれば良い。&br;  しかし、それだけではこのスクリプトは動作しない。&br; なぜならば、書き込んだ場所が onCollide 属性であるからだ。&br; onCollide 属性は、「その物質が他の物質に衝突した際に、書かれているThymeスクリプトを実行する」という属性であるため&br; Thymeスクリプトを動作させるためには、かならずしも「なにかに衝突させること」が必要である。&br; ( 上記2つのスクリプトに限って言えば、衝突させる相手は何でも構わない )  各例文の最後についてある「;」は「式がここで終わり」という意味の記号である&br; 1つの式のみをスクリプトメニューに記載した場合、決定した時に「;」が消えてしまうが、これはPhunの仕様である。&br; どうやら、「式の数にかかわらず、最後の;は省略する」というルールが存在しているようである。&br; この解説においては、式の数にかかわらず;を表記すると、断りを入れておく。 &br; *基礎的なあれこれ **§いつどこでどのようにスクリプトが動くのか Thymeスクリプトを実行出来る場所は2箇所ある。 +F11キーを押して現れるコンソール画面への直接入力 +物質を選択後、メニュー「スクリプトメニュー」内の「onCollide」属性への記述 ---- **§値と変数 式に用いる数値や文字のことを総称して値(あたい)と言う。値には定数と変数の2種がある。 -定数とは「値が固定されているもの」であり、明確に数値が表記されているものである。 -変数とは「名前の付けられた箱」であり、その中に入っている値を変更できるものである。 以下に例として4行の計算を示し、解説をする。 |CENTER:80|100|220|c |行番号|CENTER:内容|CENTER:説明| |1行目|x := 3;|xという変数を内容「 3 」で作成| |2行目|x = x + 4 - 5;|xに『 x + 4 - 5 』の計算結果を入れる| |3行目|y := x + x;|yという変数を内容『 x + x 』で作成| |4行目|y = x + y;|yに『 x + y 』の計算結果を入れる| &bold(){1行目}&br; x := 3; 「xを3という内容で作成します」という意味の式。&br; 変数を始めに作成する演算子「:=」を用いている。&br; 変数には必ず初期値が必要であり、この場合は「3」である。&br; &bold(){2行目}&br; x = x + 4 - 5; 「xに『 x + 4 - 5 』の計算結果を入れる」という意味の式。&br; 変数の値を変更する演算子「=」を用いている。&br; xの値は3であるため『x+4-5』は2となり、xの値が2に変更される。&br; &bold(){3行目}&br; y := x + x; 「yという変数を内容『 x + x 』で作成します」という意味の式。&br; 初期値に「すでに作成済みである変数を用いた計算式」を使用しても問題ない。&br; つまりこの式は「 y := 2 + 2; 」と同義であり、yの初期値は4になる。&br; &bold(){4行目}&br; y = x + y; 「yに『 x + y 』の計算結果を入れる」という意味の式。&br; xは2でありyは4であるため、この式は「y= 2 + 4;」と同義である。&br; 結果としてyの値は6になる。&br; -注意事項 実際に変数を作成し使用する際には、変数名の前に「Scene.my.」をつけなければならない。&br; この決まりに従って上記の例を実際に使用する場合、以下のようになる&br; Scene.my.x := 3; Scene.my.x = Scene.my.x + 4 - 5; Scene.my.y := Scene.my.x + Scene.my.x; Scene.my.y = Scene.my.x + Scene.my.y; &br; ---- ***配列 変数の種類として「配列」がある。&br; 変数は1つに対して1つの値しか持てないが、配列は複数個の値を持つことが出来る。&br; イメージとしては「1つの名前を共有する複数の箱があり、それは番号で区別される」といったものである。&br; 実際に配列を使用している例を以下に示す。&br; Scene.my.x := [ 1 , 5 , 10 , 999 , 7 ]; Scene.my.y := Scene.my.x(0); Scene.my.z := Scene.my.x(2) + Scene.my.x(3); 順を追って解説していこう。&br; -1行目 ここでScene.my.xという配列を作成している。 --配列を作る際の書式は「 変数名 := [ 配列の内容 ]; 」である。&br; この配列の内容を書き表すと以下のようになる。&br; |CENTER:100|CENTER:100|CENTER:100|CENTER:100|CENTER:100|c |scene.my.x(0)|scene.my.x(1)|scene.my.x(2)|scene.my.x(3)|scene.my.x(4)| |1|5|10|999|7| -2行目 変数Scene.my.yを作成し、その内容としてScene.my.xの0番目を指定している。 --配列の内容を指定する書式は「 変数名(番号) 」である。 --この際注意する点は「番号は0から始まる」ということである。つまり、Scene.my.xの中身は0~4番までの5つ存在する。 -3行目 変数Scene.my.zを作成し、その内容として「Scene.my.xの2番目と3番目を加算した値」を指定している。 --Scene.my.xの2番目は10、3番目は999であるため、Scene.my.zの値は1009となる。&br; &br; 尚、配列の内容を書き換える際には注意が必要である。&br; scene.my.x := [ 1 , 2 , 3 ]; scene.my.x(2) = 99; 上記のスクリプトは「scene.my.x の2番目の内容を99に書き換える」ことを意図したものであるが&br; これはその意図通りには動かない。&br; 配列の中身を部分的に書き換える際には、非常に面倒くさい式になるが&br; scene.my.x := [ 1 , 2 , 3 ]; scene.my.x = [ scene.my.x(0) , scene.my.x(1) , 99 ]; と、このように書くしかない。&br; &br; ---- **§データ型 面倒な話だが、これはどうしても避けて通れない スクリプトで扱う値は4つに分類されている。 分類のされ方は以下のとおり |CENTER:|||c |型名|CENTER:内容|CENTER:例| |文字列型|1文字以上の文字列| "" "A"  "B" "AABB" "あいうえお" | |浮動小数点型|小数点以下を含む数字| 0.0 1.5 1.0001 10000.0 | |整数型|小数点以下がない数字| 0 1 100 10000| |ブール型|正か偽を表現| true  false | -注意するべきは、整数型と浮動小数点型の違いである。 -「0」は整数だが「0.0」は浮動小数点となる。同様に「1」は整数だが「1.0」は浮動小数点である。 -文字列型の「""」は「0文字のテキストデータ」を表している。 以下に物質のスクリプトメニュー内の各項目について型を示す。 |CENTER:100|CENTER:200|c |項目名|データ型| |airFrictionrMult =|浮動小数点| |attraction =|浮動小数点| |collideSet =|整数| |collideWater =|ブール| |color =|浮動小数点(配列、要素数4)| |controllerAcc =|浮動小数点| |controllerInvertX =|ブール| |controllerInvertY =|ブール| |controllerReverseXY =|ブール| |density =|浮動小数点| |drawBorder =|ブール| |friction =|浮動小数点| |heteroCollide =|ブール| |immortal =|ブール| |killer =|ブール| |onCollide =|関数| |opaqueBorders =|ブール| |restitution =|浮動小数点| |ruler =|ブール| |text =|文字列| |textColor =|浮動小数点(配列、要素数4)| |textScale|浮動小数点| |texture|文字列| |textureMatrix|浮動小数点(配列、要素数9)| ---- ***式の処理順序、データ型の優先順位 式には細かな処理の順番がある。&br; たとえば「 x = 1 + 2 + 3 + 4 + 5; 」という式は&br; 「 x = (((( 1 + 2) + 3 ) + 4 ) + 5 ); 」この括弧のもっとも内側から順に処理される。&br; 型にも優先順位があり、以下のようになっている。&br; -文字列型 > 浮動小数点型 > 整数型&br; -文字列型 > ブール型&br; これは、「異なる型の値同士を処理する際に、結果を何型にするか」というものであり&br; 下位のものと上位のものを同じ式で扱う場合、式の結果は上位の型になる。&br; 例として以下のさまざまな式について、計算結果を見ていこう。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + 2 + 3; | 6 | 整数 | | x = 1 + 2 + 3.0; | 6.0 | 浮動小数点 | 整数のみの式は結果も整数。浮動小数点型が1つでも含まれる場合、浮動小数点になる。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + "A";| "1A" | 文字列 | | x = 1.0 + "A"; | "1A" | 文字列 | | x = "A" + 1.0; | "A1" | 文字列 | 文字列と整数、浮動小数点の演算は、結果文字列となる。&br; 尚この際に1.0や2.0などの小数点以下が0の浮動小数点については、小数点以下は省略される。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + 2 + 3 + "A"; | "6A" | 文字列 | | x = 1 + "A" + 2 + 3; | "1A23" | 文字列 | 上の式だと、「1+2+3」が処理されるまでは整数の足し算であり、「+"A"」で最後に文字列型になる。&br; 下の式では、最初の「1+"A"」の結果が「"1A"(文字列型)」となり、それ以降の演算も「文字列型+整数型」となるため結果が「"1A23"」となる。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + 2.2 + "A" + "B"; | "3.2AB" | 文字列 | | x = 1 + 2.2 + "A" + true; | "3.2Atrue" | 文字列 | 上の式は特に解説の必要はないと思われる。&br; 下の式は、「1+2.2+"A"」が「"3.2A"」となり、その後「"3.2A"+ true」つまり「文字列型+ブール型」の演算となる。&br; ブール型の値「true」は文字列と演算する際には、そのままの文字「"true"」として扱われるため&br; 結果として「"3.2A" + "true"」と同義である。したがって結果は「"3.2Atrue"」となる。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + true; | (演算不可) | - | | x = 1 + "" + true; | "1ture" | 文字列 | | x = true + 1.0; | (演算不可) | - | | x = true + "" + 1.0; | "true1" | 文字列 | 整数型とブール型の演算については演算不可となりエラーが起きる。浮動小数点型も同じく。&br; ただし、整数と文字列型、文字列型とブール型は演算できるため、途中に「""(空の文字列)」をはさめば演算が行える。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c | x = true + true + "" + 1 | (演算不可) | - | | x = true + "" + true + 1 | "truetrue1" | 文字列 | ブール型同士の四則演算も演算不可である。&br; ただしこれも間に空文字列を挟むことにより演算は行える。&br; ---- **§演算子 演算に使用する記号を総称して「演算子」と呼ぶ。 -演算子の左辺と右辺には値がくる(三項演算子は除外) -演算子は総じて演算結果である値を残す 要は「+」や「-」などといった計算記号のことである。&br; 以下に演算子を分類ごとに紹介する。&br; ***数値を扱う場合 -算術演算子 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |+|加算|3 + 4|7| |~|~|3 + 4.0|7.0| |-|減算|5 - 2|3| |~|~|5 - 2.0|3.0| |*|乗算|4 * 5|20| |~|~|4 * 5.0|20.0| |/|除算|8 / 4|2| |~|~|8 / 5|1| |~|~|8 / 5.0|1.6| |%|剰余|8 % 5|3| |~|~|8 % 5.0|3.0| |^|累乗|2 ^ 3|8| |~|~|10 ^ 3|1000| -基本的には浮動小数点と整数の演算は、結果が浮動小数点になることに気をつけておけばよい。&br; -除算の場合は、割る数が整数ならば演算結果も整数だが、割る数が浮動小数点ならば小数点以下も計算される。&br; -剰余とは割り算の余りのことである。浮動小数点を含む計算でも問題なく余りが求められる。&br; &br; -関係演算子 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |==|等しい|1 == 1|true| |~|~|1 == 2|false| |!=|等しくない|1 != 1|false| |~|~|1 != 2|true| | >|大なり|1 > 2|false| |~|~|2 > 1|true| |<|小なり|1 < 2|true| |~|~|2 < 1|false| |>=|以上|1 >= 1|true| |~|~|1 >= 2|false| |<=|以下|1 <= 1|true| |~|~|2 <= 1|false| &br; ***文字列を扱う場合 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |+|加算|"ABC" + "DE"|"ABCDE"| |==|等しい|"AB" == "AB"|true| |!=|等しくない|"AB" != "ab"|true| -Thymeで文字列に対して行うことがある演算はこの3つしかないと思われる -大なり小なりの比較演算なども行えるが、行うことはないであろう -尚、加算以外の算術演算子は全てエラーとなる &br; ***ブール限定の演算 細かい話は抜きにして「ブール型にのみ用いられる演算でありその結果もすべてブール型である」と覚えておけば良い。&br; true=真 か false=偽 を判断する際に用いる。&br; 以下の表が、その演算内容のすべてである。&br; -論理演算子 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |&&|論理積(and)|true && true|true| |~|~|true && false|false| |~|~|false && true|false| |~|~|false && false|false| ||||論理和(or)|true || true|true| |~|~|true || false|true| |~|~|false || true|true| |~|~|false||false|false| |!|否定(not)|!true|false| |~|~|!false|true| -wikiの書式上の問題で論理和の演算子を全角文字で表記している。実際には半角(||)である。&br; -論理積(and)は「両辺共にtrueならばtrue、それ以外はfalse」 -論理和(or)は「両辺どちらかがtrueならばtrue、共にfalseの場合のみfalse」 -否定(not)は値を一つしか対象とせず「真偽値を逆転させる」 &br; ***配列に対する演算 -演算が要素ごとに行われるもの |CENTER:80|CENTER:80|CENTER:280|CENTER:250|c |演算子|意味|例文|演算結果| |+|加算|[1,2,3] + [1,3,5]|[2,5,8]| |-|減算|[4,5,6] - [1,2,3]|[3,3,3]| |*|乗算|[1,2,3] * [2,3,4]|[2,6,12]| |/|除算|[12,12,12] / [2,3,4]|[6,4,3]| |&&|論理積|[true,true,false] && [true,false,true]|[true,false,false]| ||||論理和|[true,true,false]||[true,false,false]|[true,true,false]| -演算子の左辺の0番目と右辺の0番目、同様に1番と1番というように、それぞれの要素同士で演算が行われる。 -演算子の両辺が同じ要素数でなければエラーとなり、演算は行われない。 &br; -演算は配列全体で行われるもの |CENTER:80|CENTER:80|CENTER:280|CENTER:250|c |演算子|意味|例文|演算結果| |*|乗算|2 * [1,2,3]|[2,4,6]| |*|~|[2,3,4] * 2|[4,6,8]| |/|除算|2 / [1,2,3]|(error)| |/|~|[2,4,8] / 2|[1,2,3]| |==|等しい|[1,2,3] == [1,2,3]|true| |!=|等しくない|[1,2,3] != [1,2,3]|false| |++|結合|[1,2,3] ++ [4,5,6]|[1,2,3,4,5,6]| -乗算については、前後関係に問わず演算可能である。 -除算は、割られる数が配列で割る数が整数もしくは浮動小数点ならば演算が可能である。 -等しいか等しくないかの判断は全体で行われる。ひとつでも要素の内容が違っていれば不等号扱いである。 -結合演算子は両辺の要素全てを左辺→右辺の順に持つひとつの配列を結果とする。 &br; ---- **§その他、覚えておくべきこと ---- ***使用できる変数について スクリプト内で使用できる変数は「そのスクリプトがどこに書かれているものか」によって変わる。&br; それらを3つに分類し、それぞれについて使用可能な変数をまとめたものが以下。&br; +F11キーで現れるコンソール画面に書き込んだ場合 --[[スクリプト言語Thyme>Thyme]]のページに記載のある「App.~Sim.」までの全て ---実際に使用する際には「FileInfo.author」や「math.pi」といった表記で用いる ---表の「変数型」の部分については英語表記なので以下の表を参照 |表記|意味| |decimal|十進数| |integer|整数| |value|値| |positive|正の(0より大きい)| |true or false|真か偽| |function|関数(※後述参照)| |array of |配列である| |string|文字列| |constant|定数| |sub-group|内部に変数や関数を持つグループ名| |Read only|読み取りのみ可能(値を変更不可)| ---※説明文部分については、各自で翻訳してくださいな。 ---※使用頻度の高そうなものについては、応用編にて紹介と解説を行うので、そちらを参照してください +物質のスクリプトメニューに書き込んだ場合(onCollide以外) --上記コンソール画面で使用できる変数全てを使用可能 --その物質自身のスクリプトメニュー内の全ての項目をそのまま変数として使用可能。 ---表記は項目名をそのまま「density」や「text」と、項目名自体が変数名となる。 +物質のスクリプトメニュー内onCollide部分に書き込んだ場合 --上記の全ての変数を使用可能 --それに加えて、衝突した相手の変数を使用可能 ---表記は「e.other.text」や「e.other.color」など、項目名の前に「e.other.」を付け足したものである。 ※[[スクリプト言語Thyme>Thyme]]ページの「衝突した相手の物質のタイプを得る」と「e.normalの解説」に興味深い話が載っている&br; 今は理解できないという方でも、講座を最後まで理解したあとで読んでみるべし&br; &br; ---- *実用的なお話へ **§条件分岐構造と三項演算子 これ抜きには複雑なThymeスクリプトなど組めない、と言っても過言ではない。&br; &br; ---- ***条件分岐構造 ある変数Aがあり、Aが1ならば処理1を実行し、Aが2なら処理2を実行する。端的に言うとそういうことである。&br; 何はともあれ実例を見ていただきたい&br; scene.my.x := 2; scene.my.y := ( scene.my.x == 3 )?( scene.my.x + 3 ):( scene.my.x + 10 ); 1行目は特に解説の必要はないと思われる。&br; 2行目はscene.my.y変数を作成しているのだが、その中身に条件分岐を用いている。&br; 2行目の「:=」以降の部分が条件分岐構造になっており&br; 「 『scene.my.x==3』が真ならば『scene.my.x + 3』、そうでなければ『scene.my.x + 10』 」という意味である。&br; この場合 scene.my.x は 2 なので、『scene.my.x + 10』が選ばれ、scene.my.yの値は12となる。&br; &br; ---- ***三項演算子 先ほどの例で条件分岐のために用いた演算子を「三項演算子」と言う。&br; 使用方法は以下のとおりである。&br; 判定条件 ? 条件が真の場合の処理内容 : 条件が偽の場合の処理内容 -判定条件の部分は関係演算、もしくは論理演算などを用いてブール型の値でなければならない。&br; &br; -処理内容部分は1文であるならば;は省略可能。&br; -処理内容が複数行ある場合は、それらを{}で囲む必要がある。&br; (scene.my.x == 2) ? scene.my.y = 5; scene.my.z = 3; : scene.my.y = 1; scene.my.z = 10; ; (×エラー) (scene.my.x == 2) ?{ scene.my.y = 5; scene.my.z = 3 }:{ scene.my.y = 1; scene.my.z = 10 }; (○正常動作) &br; 条件部分で複雑な式を書き、細かな条件判定をすることも可能。&br; onCollide = (e) =>{ e.this.density = (( e.other.collideSet == 2 )&&( e.other.density == 100.0 ))?{ 50.0 }:{ 2.0 }; } 条件分岐部分は「『衝突相手の衝突判定がBのみであり、かつ密度が100.0』ならば 50.0 、違うならば 2.0 」という意味である。&br; それを e.this.density つまりは自分自身の密度へ書き込んでいる。&br; まとめると「衝突相手の衝突判定がBであり密度が100.0ならば、自分自身が密度50.0になり、違うならば2.0になる」&br; という動作をするスクリプトである。&br; &br; ---- **§関数 ---- ***関数とは何か さて、だいぶ小難しい話になるところなので、腰を落ち着けてじっくりと読んでいただきたい。&br; 「関数」といきなり言っても通じないであろうから、まずPhun抜きにして以下の事例をごらんいただこう。&br; +あなたは書類の整理をしていて、一人の友達に手伝ってもらうことになった。 +あなたは友達に2種類の仕事を頼みたい。そのどちらも、かなりの回数あり、順不同に頼みたい。 +2種類の仕事をA、Bと呼び名をつける。 +そしてAのときはこういう物を渡すから、こう処理して欲しい。Bのときはこう。とそれぞれ内容を定め教える。 +それ以降はあなたは友達に「Aだよ、はいこれ」と名称と共に物を渡すだけ。 +ひとつの仕事が終わるたび友達はあなたに「できたよ、はいどうぞ」と完成書類を返してくれる。 実に効率的でよろしい話である。&br; &br; 実は上記の話でA、Bと名づけたものこそが「関数」なのだ。&br; つまり「あらかじめ手順と渡すものを決めておくことで、規定された処理を行ってくれるもの」なのである。&br; &br; 関数を実際に見る前に「引数」と「戻り値」というものについて、上記の話にからめて知っていただこう。&br; 「引数(ひきすう)」とは「Aを頼む際には大きな書類2枚と小さな書類1枚を渡すよ」といった場合の、その書類である。&br; 関数を実行する際には「0個以上の引数」が必要である。これは関数を作成する際に取り決める。&br; 「戻り値(もどりち)」とは「仕事が終わったら、その完成品を渡してね」といった場合の、その完成品である。&br; 関数は「必ず1つの戻り値」を持つ。&br; &br; ---- ***作成と使用 それでは、実際に関数を作成し、使用する例を見てみよう&br; Scene.my.func1 := (var) => { var % 2 == 0 ? true : false }; Scene.my.x = Scene.my.func1(2); 1行目で関数を製作し、2行目で使用している。&br; 関数の内容としては「引数が偶数ならばtrue、奇数ならfalseを戻り値とする」である。&br; つまりは偶数か奇数かを判定するための関数だ。&br; &br; 関数の書式は以下のとおりである&br; 関数名 = ( 引数名 ) => { 処理内容 } -関数名はもちろん「Scene.my.」をつけることを忘れてはならない -引数は「0個以上」と定められているので、引数が必要ない関数ならば何も表記しなくてよい。 --引数は2つ以上でも構わなく、その場合は「,」で区切って宣言する。 -処理内容も2行以上でも構わない。その際はきっちり1行ごとに「;」で区切ること。 &br; 尚、関数の作成を行う際にはF11キーで現れるコンソール画面から作成する必要がある。&br; ちなみに、たとえその関数がonCollide内に書かれていても「e.other.○○」や「e.this.○○」などの変数は使用できない。&br; 関数内で使用したい値については基本的に引数で渡してやらねばならない。&br; ただし、Phun自体が持っている変数については使用することが出来る。(「Sim.○○」や「App.○○」など)&br; &br; 以下にいくつかの関数の作成例を示す&br; &br; -三角形の高さと幅を引数として渡すと、その面積を求める関数 (引数が2つある関数) ◇関数   scene.my.triangle := ( width , height ) => { width * height * 0.5 }; ◇使用例   scene.my.x = scene.my.triangle( 3.0 , 5.0 );   scene.my.x には 3.0 * 5.0 * 0.5 の演算結果 7.5 が入る。&br; &br; -シミュレーション経過時間0.5秒ごとに戻り値がtrueとfalseで入れ替わる関数 (引数を持たない関数) ◇関数   scene.my.blink := () => { sim.time % 1.0 >= 0.5 ? true : false }; ◇使用例 onCollide = (e) =>{   text = { "" + ( scene.my.blink ? "Yes" : "No" ) }; }   書かれた物質のtext属性値が0.5秒ごとに "Yes" と "No" 交互に変わる。&br; &br; ---- ***用意されている関数 あらかじめPhunのシステム上に作成されていて、使用可能な関数はいくつもある。&br; かなりの量であるが、実際に使用する可能性のあるものは限られる。&br; 使用頻度の高い関数をいくつか書き留めておこう。&br; &br; -数学関数 |CENTER:80|CENTER:180|CENTER:180|c |関数名|引数|戻り値| |math.asin(x)|浮動小数点型|逆三角関数 arcsin(x)の値| |math.acos(x)|浮動小数点型|逆三角関数 arccos(x)の値| |math.atan(x)|浮動小数点型|逆三角関数 arctan(x)の値| |math.sin(x)|浮動小数点型、単位は[rad]|三角関数 sin(x)の値| |math.cos(x)|浮動小数点型、単位は[rad]|三角関数 cos(x)の値| |math.tan(x)|浮動小数点型、単位は[rad]|三角関数 tan(x)の値| -Scene属関数(主に物質の生成) |CENTER:140|CENTER:80|CENTER:80|c |関数名|引数|戻り値| |scene.addBox{ x }|(後述)|"box"| |scene.addCircle{ x }|(後述)|"circle"| |scene.addFixjoint{ x }|(後述)|"fixjoint"| |scene.addHinge{ x }|(後述)|"hinge"| |scene.addPen{ x }|(後述)|"pen"| |scene.addPlane{ x }|(後述)|"plane"| |scene.addPolygon{ x }|(後述)|"polygon"| |scene.addSpring{ x }|(後述)|"spring"| |scene.addWater{ x }|(後述)|"water"| |scene.EraseWater|(なし)|(なし)| add****{}タイプの関数の引数については、[[phn形状について]]を参照にしてほしい。&br; というだけも味気ないので、2つの例を以下に挙げておく&br; &br; -位置[10.0,25.5]に、幅15.0 高さ20.0 密度10.0のboxを追加するスクリプト scene.addBox{ pos = [ 10.0 , 25.5 ]; size = [ 15.0 , 20.0 ]; density = 10.0 }; &br; -横長の長方形に、二つの丸をヒンジで接続するスクリプト scene.addBox{ pos = [ 0.0 , 0.0 ]; size = [ 6.0 , 2.0 ]; geomID = 100; }; scene.addCircle{ pos = [ 2.0 , -0.5 ]; radius = 0.8; geomID = 101 }; scene.addCircle{ pos = [-2.0 , -0.5 ]; radius = 0.8; geomID = 102 }; scene.addHinge{ geom0 = 100; geom0pos = [ 2.0 , -0.5 ]; geom1 = 101; geom1pos = [ 0.0 , 0.0 ] }; scene.addHinge{ geom0 = 100; geom0pos = [-2.0 , -0.5 ]; geom1 = 102; geom1pos = [ 0.0 , 0.0 ] }; &br; ※追記 Thymeで物体を発生させる場合、速度と角速度も指定できる。両方共に「じょうほう」メニューで表示されている単位(速度 m/s, 角速度 rad/s)で指定する。 -x速度20m/s、y速度10m/s、角速度30rad/sの円を発生させるスクリプト scene.addBox({vel := [20.0, 10.0]; angVel := 30}); &br ---- **§配列の応用 配列の解説部分で作った配列のような1列しかない配列は、1次元配列と言う。&br; 1次元という呼び名があるからには、2次元配列ももちろん存在する。&br; 作成の仕方と使用の仕方を以下に示す。&br; scene.my.x := [ [1,2,3] , [4,5,6] ]; これが2行3列の2次元配列である。&br; 配列の0番目の値として「要素3の配列」が入っており、1番目の値にも「要素3の配列」が入っている。&br; これを使用する際には以下のように書く&br; scene.my.y := scene.my.x(0)(1); scene.my.xの0行目の1番目を指定している。&br;この時scene.my.yに入る値は「2」である。&br; scene.my.xの内容を視覚的にわかりやすく表にまとめると、以下のようになる。&br; -scene.my.x(A)(B) |CENTER:50|CENTER:50|CENTER:50|CENTER:50|c |\|B=0|B=1|B=2| |A=0|1|2|3| |A=1|4|5|6| ちなみに、2次元配列を作る際に、列の値は必ずしも全て揃える必要はない。&br; 更に、データ型はそれぞれの要素ごとに記録されるため、揃える必要はない。(これは1次元配列でも同じく)&br; つまり、以下のような配列も生成可能である。&br; scene.my.x := [ [ 11 , 12 , 13 ],[ "welcome" , 2 , "phun"],[ 21 , 22 , 23 , 24 , 25 ] ]; scene.my.y := [ [ "one" , 2 , "three" ],"welcome",[ true , "or" , false ],[ "Let's" , "phun" ] ]; それぞれ内容は以下のようになる。 -scene.my.x(A)(B) |CENTER:70|CENTER:100|CENTER:100|CENTER:100|CENTER:100|CENTER:100|c |\|B=0|B=1|B=2|B=3|B=4| |A=0|11|12|13|(error)|(error)| |A=1|"welcome"|2|"phun"|(error)|(error)| |A=2|21|22|23|24|25| -scene.my.y(A)(B) |CENTER:70|CENTER:100|CENTER:100|CENTER:100|c |\|B=0|B=1|B=2| |A=0|"one"|2|"three"| |A=1|(error)|(error)|(error)| |A=2|true|"or"|false| |A=3|"Let's"|"phun"|error| -scene.my.x(1)(4) や scene.my.y(3)(2) など、表記が(error)のものは使用することが出来ない。 -scene.my.y の A=1の場合は、そこだけ1次元配列のままなので、"welcome" を参照したければ「scene.my.y(1)」と表記する。 &br; ---- *大きな間違いの訂正とお詫び  講座の書き出し時点で「ThymeスクリプトをonCollide属性以外にも書き込み可能だ」と書きましたが間違いであることが分かりました。&br; 書いたそのときは動きはすれど、Phunを終了させたりファイルに保存する際に、onCollide以外の属性に書いたスクリプトは保存されない&br; ことが多いという事実が判明しました。&br;  紛らわしい文章を載せてしまい、まことに申し訳ありませんでした。(現在は訂正済み)          2010/08/23 08:08 作成主 ---- *コメント欄 #pcomment(7)
#contents(,option=word) *&bold(){Thyme講座} Thymeは初心者やプログラム経験のない方にとってはハードルが高い。思いつきではあるが、ここにThyme講座を書きなぐっていきたいと思う。&br; 尚思いつきかつ、筆者も独学にちかい部分があるため、不明瞭な部分や間違い等があると予想される。&br; そのような部分を発見した場合、コメントにて指摘いただけるとありがたい。&br; &br; *なにはともあれ書き方と例文 まずスクリプトがどのようなものなのか、見ていただこう。&br; &br; 物質のテキスト文章部分にシミュレーション開始からの経過時間を表示させるスクリプト text = { "" + sim.time }; &br; 常に物質の色を変え続けるスクリプト color = { [ sim.time % 1.0 , sim.time * 0.5 % 1.0 , sim.time * 0.3 % 1.0 , 1.0 ] };  このような1処理分の塊を「式」という。&br; 式1つは「○○○ = ○○○」の形をとる。  ただし、スクリプトメニューをよく見ると「text =」や「color =」は既に記述されている。&br; このため、1つ目を例を実際に使用したい場合は「{ "" + sim.time }」を「text =」項目の内容部分に記述すれば良い。 尚、各例文の最後についてある「;」は「式がここで終わり」という意味の記号である&br; 1つの式のみをスクリプトメニューに記載した場合、決定した時に「;」が消えてしまうが、これはPhunの仕様である。&br; どうやら、「式の数にかかわらず、最後の;は省略する」というルールが存在しているようである。&br; この解説においては、式の数にかかわらず;を表記すると、断りを入れておく。 &br; *基礎的なあれこれ **§いつどこでどのようにスクリプトが動くのか Thymeスクリプトを実行出来る場所は2箇所ある。 +F11キーを押して現れるコンソール画面への直接入力 +物質を選択後、メニューの「スクリプトメニュー」内の各属性値への記述 [[スクリプト言語Thyme]]のページには、onCollide属性内以外への記述については特に述べられていないが&br; 書式さえ守ればどの属性内にも直接スクリプトを記述できる。 onCollide以外の属性へ書き込む場合の注意点としては以下の2つ。 +「{ (スクリプト内容) }」の形式で書き込むこと({ }で囲む) +各属性ごとに決められているデータ型と、スクリプトが出力する値の型を合わせる事 どちらかの条件が満たされていない場合、書き込んだあとに決定しても編集前の状態に戻ってしまう。 ---- **§値と変数 式に用いる数値や文字のことを総称して値(あたい)と言う。値には定数と変数の2種がある。 -定数とは「値が固定されているもの」であり、明確に数値が表記されているものである。 -変数とは「名前の付けられた箱」であり、その中に入っている値を変更できるものである。 以下に例として4行の計算を示し、解説をする。 |CENTER:80|100|220|c |行番号|CENTER:内容|CENTER:説明| |1行目|x := 3;|xという変数を内容「 3 」で作成| |2行目|x = x + 4 - 5;|xに『 x + 4 - 5 』の計算結果を入れる| |3行目|y := x + x;|yという変数を内容『 x + x 』で作成| |4行目|y = x + y;|yに『 x + y 』の計算結果を入れる| &bold(){1行目}&br; x := 3; 「xを3という内容で作成します」という意味の式。&br; 変数を始めに作成する演算子「:=」を用いている。&br; 変数には必ず初期値が必要であり、この場合は「3」である。&br; &bold(){2行目}&br; x = x + 4 - 5; 「xに『 x + 4 - 5 』の計算結果を入れる」という意味の式。&br; 変数の値を変更する演算子「=」を用いている。&br; xの値は3であるため『x+4-5』は2となり、xの値が2に変更される。&br; &bold(){3行目}&br; y := x + x; 「yという変数を内容『 x + x 』で作成します」という意味の式。&br; 初期値に「すでに作成済みである変数を用いた計算式」を使用しても問題ない。&br; つまりこの式は「 y := 2 + 2; 」と同義であり、yの初期値は4になる。&br; &bold(){4行目}&br; y = x + y; 「yに『 x + y 』の計算結果を入れる」という意味の式。&br; xは2でありyは4であるため、この式は「y= 2 + 4;」と同義である。&br; 結果としてyの値は6になる。&br; -注意事項 実際に変数を作成し使用する際には、変数名の前に「Scene.my.」をつけなければならない。&br; この決まりに従って上記の例を実際に使用する場合、以下のようになる&br; Scene.my.x := 3; Scene.my.x = Scene.my.x + 4 - 5; Scene.my.y := Scene.my.x + Scene.my.x; Scene.my.y = Scene.my.x + Scene.my.y; &br; ---- ***配列 変数の種類として「配列」がある。&br; 変数は1つに対して1つの値しか持てないが、配列は複数個の値を持つことが出来る。&br; イメージとしては「1つの名前を共有する複数の箱があり、それは番号で区別される」といったものである。&br; 実際に配列を使用している例を以下に示す。&br; Scene.my.x := [ 1 , 5 , 10 , 999 , 7 ]; Scene.my.y := Scene.my.x(0); Scene.my.z := Scene.my.x(2) + Scene.my.x(3); 順を追って解説していこう。&br; -1行目 ここでScene.my.xという配列を作成している。 --配列を作る際の書式は「 変数名 := [ 配列の内容 ]; 」である。&br; この配列の内容を書き表すと以下のようになる。&br; |CENTER:100|CENTER:100|CENTER:100|CENTER:100|CENTER:100|c |scene.my.x(0)|scene.my.x(1)|scene.my.x(2)|scene.my.x(3)|scene.my.x(4)| |1|5|10|999|7| -2行目 変数Scene.my.yを作成し、その内容としてScene.my.xの0番目を指定している。 --配列の内容を指定する書式は「 変数名(番号) 」である。 --この際注意する点は「番号は0から始まる」ということである。つまり、Scene.my.xの中身は0~4番までの5つ存在する。 -3行目 変数Scene.my.zを作成し、その内容として「Scene.my.xの2番目と3番目を加算した値」を指定している。 --Scene.my.xの2番目は10、3番目は999であるため、Scene.my.zの値は1009となる。&br; &br; 尚、配列の内容を書き換える際には注意が必要である。&br; scene.my.x := [ 1 , 2 , 3 ]; scene.my.x(2) = 99; 上記のスクリプトは「scene.my.x の2番目の内容を99に書き換える」ことを意図したものであるが&br; これはその意図通りには動かない。&br; 配列の中身を部分的に書き換える際には、非常に面倒くさい式になるが&br; scene.my.x := [ 1 , 2 , 3 ]; scene.my.x = [ scene.my.x(0) , scene.my.x(1) , 99 ]; と、このように書くしかない。&br; &br; ---- **§データ型 面倒な話だが、これはどうしても避けて通れない スクリプトで扱う値は4つに分類されている。 分類のされ方は以下のとおり |CENTER:|||c |型名|CENTER:内容|CENTER:例| |文字列型|1文字以上の文字列| "" "A"  "B" "AABB" "あいうえお" | |浮動小数点型|小数点以下を含む数字| 0.0 1.5 1.0001 10000.0 | |整数型|小数点以下がない数字| 0 1 100 10000| |ブール型|正か偽を表現| true  false | -注意するべきは、整数型と浮動小数点型の違いである。 -「0」は整数だが「0.0」は浮動小数点となる。同様に「1」は整数だが「1.0」は浮動小数点である。 -文字列型の「""」は「0文字のテキストデータ」を表している。 以下に物質のスクリプトメニュー内の各項目について型を示す。 |CENTER:100|CENTER:200|c |項目名|データ型| |airFrictionrMult =|浮動小数点| |attraction =|浮動小数点| |collideSet =|整数| |collideWater =|ブール| |color =|浮動小数点(配列、要素数4)| |controllerAcc =|浮動小数点| |controllerInvertX =|ブール| |controllerInvertY =|ブール| |controllerReverseXY =|ブール| |density =|浮動小数点| |drawBorder =|ブール| |friction =|浮動小数点| |heteroCollide =|ブール| |immortal =|ブール| |killer =|ブール| |onCollide =|関数| |opaqueBorders =|ブール| |restitution =|浮動小数点| |ruler =|ブール| |text =|文字列| |textColor =|浮動小数点(配列、要素数4)| |textScale|浮動小数点| |texture|文字列| |textureMatrix|浮動小数点(配列、要素数9)| ---- ***式の処理順序、データ型の優先順位 式には細かな処理の順番がある。&br; たとえば「 x = 1 + 2 + 3 + 4 + 5; 」という式は&br; 「 x = (((( 1 + 2) + 3 ) + 4 ) + 5 ); 」この括弧のもっとも内側から順に処理される。&br; 型にも優先順位があり、以下のようになっている。&br; -文字列型 > 浮動小数点型 > 整数型&br; -文字列型 > ブール型&br; これは、「異なる型の値同士を処理する際に、結果を何型にするか」というものであり&br; 下位のものと上位のものを同じ式で扱う場合、式の結果は上位の型になる。&br; 例として以下のさまざまな式について、計算結果を見ていこう。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + 2 + 3; | 6 | 整数 | | x = 1 + 2 + 3.0; | 6.0 | 浮動小数点 | 整数のみの式は結果も整数。浮動小数点型が1つでも含まれる場合、浮動小数点になる。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + "A";| "1A" | 文字列 | | x = 1.0 + "A"; | "1A" | 文字列 | | x = "A" + 1.0; | "A1" | 文字列 | 文字列と整数、浮動小数点の演算は、結果文字列となる。&br; 尚この際に1.0や2.0などの小数点以下が0の浮動小数点については、小数点以下は省略される。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + 2 + 3 + "A"; | "6A" | 文字列 | | x = 1 + "A" + 2 + 3; | "1A23" | 文字列 | 上の式だと、「1+2+3」が処理されるまでは整数の足し算であり、「+"A"」で最後に文字列型になる。&br; 下の式では、最初の「1+"A"」の結果が「"1A"(文字列型)」となり、それ以降の演算も「文字列型+整数型」となるため結果が「"1A23"」となる。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + 2.2 + "A" + "B"; | "3.2AB" | 文字列 | | x = 1 + 2.2 + "A" + true; | "3.2Atrue" | 文字列 | 上の式は特に解説の必要はないと思われる。&br; 下の式は、「1+2.2+"A"」が「"3.2A"」となり、その後「"3.2A"+ true」つまり「文字列型+ブール型」の演算となる。&br; ブール型の値「true」は文字列と演算する際には、そのままの文字「"true"」として扱われるため&br; 結果として「"3.2A" + "true"」と同義である。したがって結果は「"3.2Atrue"」となる。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c |式|xに入る値|結果のデータ型| | x = 1 + true; | (演算不可) | - | | x = 1 + "" + true; | "1ture" | 文字列 | | x = true + 1.0; | (演算不可) | - | | x = true + "" + 1.0; | "true1" | 文字列 | 整数型とブール型の演算については演算不可となりエラーが起きる。浮動小数点型も同じく。&br; ただし、整数と文字列型、文字列型とブール型は演算できるため、途中に「""(空の文字列)」をはさめば演算が行える。&br; &br; |CENTER:200|CENTER:100|CENTER:100|c | x = true + true + "" + 1 | (演算不可) | - | | x = true + "" + true + 1 | "truetrue1" | 文字列 | ブール型同士の四則演算も演算不可である。&br; ただしこれも間に空文字列を挟むことにより演算は行える。&br; ---- **§演算子 演算に使用する記号を総称して「演算子」と呼ぶ。 -演算子の左辺と右辺には値がくる(三項演算子は除外) -演算子は総じて演算結果である値を残す 要は「+」や「-」などといった計算記号のことである。&br; 以下に演算子を分類ごとに紹介する。&br; ***数値を扱う場合 -算術演算子 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |+|加算|3 + 4|7| |~|~|3 + 4.0|7.0| |-|減算|5 - 2|3| |~|~|5 - 2.0|3.0| |*|乗算|4 * 5|20| |~|~|4 * 5.0|20.0| |/|除算|8 / 4|2| |~|~|8 / 5|1| |~|~|8 / 5.0|1.6| |%|剰余|8 % 5|3| |~|~|8 % 5.0|3.0| |^|累乗|2 ^ 3|8| |~|~|10 ^ 3|1000| -基本的には浮動小数点と整数の演算は、結果が浮動小数点になることに気をつけておけばよい。&br; -除算の場合は、割る数が整数ならば演算結果も整数だが、割る数が浮動小数点ならば小数点以下も計算される。&br; -剰余とは割り算の余りのことである。浮動小数点を含む計算でも問題なく余りが求められる。&br; &br; -関係演算子 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |==|等しい|1 == 1|true| |~|~|1 == 2|false| |!=|等しくない|1 != 1|false| |~|~|1 != 2|true| | >|大なり|1 > 2|false| |~|~|2 > 1|true| |<|小なり|1 < 2|true| |~|~|2 < 1|false| |>=|以上|1 >= 1|true| |~|~|1 >= 2|false| |<=|以下|1 <= 1|true| |~|~|2 <= 1|false| &br; ***文字列を扱う場合 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |+|加算|"ABC" + "DE"|"ABCDE"| |==|等しい|"AB" == "AB"|true| |!=|等しくない|"AB" != "ab"|true| -Thymeで文字列に対して行うことがある演算はこの3つしかないと思われる -大なり小なりの比較演算なども行えるが、行うことはないであろう -尚、加算以外の算術演算子は全てエラーとなる &br; ***ブール限定の演算 細かい話は抜きにして「ブール型にのみ用いられる演算でありその結果もすべてブール型である」と覚えておけば良い。&br; true=真 か false=偽 を判断する際に用いる。&br; 以下の表が、その演算内容のすべてである。&br; -論理演算子 |CENTER:80|CENTER:80|CENTER:150|CENTER:150|c |演算子|意味|例文|演算結果| |&&|論理積(and)|true && true|true| |~|~|true && false|false| |~|~|false && true|false| |~|~|false && false|false| ||||論理和(or)|true || true|true| |~|~|true || false|true| |~|~|false || true|true| |~|~|false||false|false| |!|否定(not)|!true|false| |~|~|!false|true| -wikiの書式上の問題で論理和の演算子を全角文字で表記している。実際には半角(||)である。&br; -論理積(and)は「両辺共にtrueならばtrue、それ以外はfalse」 -論理和(or)は「両辺どちらかがtrueならばtrue、共にfalseの場合のみfalse」 -否定(not)は値を一つしか対象とせず「真偽値を逆転させる」 &br; ***配列に対する演算 -演算が要素ごとに行われるもの |CENTER:80|CENTER:80|CENTER:280|CENTER:250|c |演算子|意味|例文|演算結果| |+|加算|[1,2,3] + [1,3,5]|[2,5,8]| |-|減算|[4,5,6] - [1,2,3]|[3,3,3]| |*|乗算|[1,2,3] * [2,3,4]|[2,6,12]| |/|除算|[12,12,12] / [2,3,4]|[6,4,3]| |&&|論理積|[true,true,false] && [true,false,true]|[true,false,false]| ||||論理和|[true,true,false]||[true,false,false]|[true,true,false]| -演算子の左辺の0番目と右辺の0番目、同様に1番と1番というように、それぞれの要素同士で演算が行われる。 -演算子の両辺が同じ要素数でなければエラーとなり、演算は行われない。 &br; -演算は配列全体で行われるもの |CENTER:80|CENTER:80|CENTER:280|CENTER:250|c |演算子|意味|例文|演算結果| |*|乗算|2 * [1,2,3]|[2,4,6]| |*|~|[2,3,4] * 2|[4,6,8]| |/|除算|2 / [1,2,3]|(error)| |/|~|[2,4,8] / 2|[1,2,3]| |==|等しい|[1,2,3] == [1,2,3]|true| |!=|等しくない|[1,2,3] != [1,2,3]|false| |++|結合|[1,2,3] ++ [4,5,6]|[1,2,3,4,5,6]| -乗算については、前後関係に問わず演算可能である。 -除算は、割られる数が配列で割る数が整数もしくは浮動小数点ならば演算が可能である。 -等しいか等しくないかの判断は全体で行われる。ひとつでも要素の内容が違っていれば不等号扱いである。 -結合演算子は両辺の要素全てを左辺→右辺の順に持つひとつの配列を結果とする。 &br; ---- **§その他、覚えておくべきこと ---- ***使用できる変数について スクリプト内で使用できる変数は「そのスクリプトがどこに書かれているものか」によって変わる。&br; それらを3つに分類し、それぞれについて使用可能な変数をまとめたものが以下。&br; +F11キーで現れるコンソール画面に書き込んだ場合 --[[スクリプト言語Thyme>Thyme]]のページに記載のある「App.~Sim.」までの全て ---実際に使用する際には「FileInfo.author」や「math.pi」といった表記で用いる ---表の「変数型」の部分については英語表記なので以下の表を参照 |表記|意味| |decimal|十進数| |integer|整数| |value|値| |positive|正の(0より大きい)| |true or false|真か偽| |function|関数(※後述参照)| |array of |配列である| |string|文字列| |constant|定数| |sub-group|内部に変数や関数を持つグループ名| |Read only|読み取りのみ可能(値を変更不可)| ---※説明文部分については、各自で翻訳してくださいな。 ---※使用頻度の高そうなものについては、応用編にて紹介と解説を行うので、そちらを参照してください +物質のスクリプトメニューに書き込んだ場合(onCollide以外) --上記コンソール画面で使用できる変数全てを使用可能 --その物質自身のスクリプトメニュー内の全ての項目をそのまま変数として使用可能。 ---表記は項目名をそのまま「density」や「text」と、項目名自体が変数名となる。 +物質のスクリプトメニュー内onCollide部分に書き込んだ場合 --上記の全ての変数を使用可能 --それに加えて、衝突した相手の変数を使用可能 ---表記は「e.other.text」や「e.other.color」など、項目名の前に「e.other.」を付け足したものである。 ※[[スクリプト言語Thyme>Thyme]]ページの「衝突した相手の物質のタイプを得る」と「e.normalの解説」に興味深い話が載っている&br; 今は理解できないという方でも、講座を最後まで理解したあとで読んでみるべし&br; &br; ---- *実用的なお話へ **§条件分岐構造と三項演算子 これ抜きには複雑なThymeスクリプトなど組めない、と言っても過言ではない。&br; &br; ---- ***条件分岐構造 ある変数Aがあり、Aが1ならば処理1を実行し、Aが2なら処理2を実行する。端的に言うとそういうことである。&br; 何はともあれ実例を見ていただきたい&br; scene.my.x := 2; scene.my.y := ( scene.my.x == 3 )?( scene.my.x + 3 ):( scene.my.x + 10 ); 1行目は特に解説の必要はないと思われる。&br; 2行目はscene.my.y変数を作成しているのだが、その中身に条件分岐を用いている。&br; 2行目の「:=」以降の部分が条件分岐構造になっており&br; 「 『scene.my.x==3』が真ならば『scene.my.x + 3』、そうでなければ『scene.my.x + 10』 」という意味である。&br; この場合 scene.my.x は 2 なので、『scene.my.x + 10』が選ばれ、scene.my.yの値は12となる。&br; &br; ---- ***三項演算子 先ほどの例で条件分岐のために用いた演算子を「三項演算子」と言う。&br; 使用方法は以下のとおりである。&br; 判定条件 ? 条件が真の場合の処理内容 : 条件が偽の場合の処理内容 -判定条件の部分は関係演算、もしくは論理演算などを用いてブール型の値でなければならない。&br; &br; -処理内容部分は1文であるならば;は省略可能。&br; -処理内容が複数行ある場合は、それらを{}で囲む必要がある。&br; (scene.my.x == 2) ? scene.my.y = 5; scene.my.z = 3; : scene.my.y = 1; scene.my.z = 10; ; (×エラー) (scene.my.x == 2) ?{ scene.my.y = 5; scene.my.z = 3 }:{ scene.my.y = 1; scene.my.z = 10 }; (○正常動作) &br; 条件部分で複雑な式を書き、細かな条件判定をすることも可能。&br; onCollide = (e) =>{ e.this.density = (( e.other.collideSet == 2 )&&( e.other.density == 100.0 ))?{ 50.0 }:{ 2.0 }; } 条件分岐部分は「『衝突相手の衝突判定がBのみであり、かつ密度が100.0』ならば 50.0 、違うならば 2.0 」という意味である。&br; それを e.this.density つまりは自分自身の密度へ書き込んでいる。&br; まとめると「衝突相手の衝突判定がBであり密度が100.0ならば、自分自身が密度50.0になり、違うならば2.0になる」&br; という動作をするスクリプトである。&br; &br; ---- **§関数 ---- ***関数とは何か さて、だいぶ小難しい話になるところなので、腰を落ち着けてじっくりと読んでいただきたい。&br; 「関数」といきなり言っても通じないであろうから、まずPhun抜きにして以下の事例をごらんいただこう。&br; +あなたは書類の整理をしていて、一人の友達に手伝ってもらうことになった。 +あなたは友達に2種類の仕事を頼みたい。そのどちらも、かなりの回数あり、順不同に頼みたい。 +2種類の仕事をA、Bと呼び名をつける。 +そしてAのときはこういう物を渡すから、こう処理して欲しい。Bのときはこう。とそれぞれ内容を定め教える。 +それ以降はあなたは友達に「Aだよ、はいこれ」と名称と共に物を渡すだけ。 +ひとつの仕事が終わるたび友達はあなたに「できたよ、はいどうぞ」と完成書類を返してくれる。 実に効率的でよろしい話である。&br; &br; 実は上記の話でA、Bと名づけたものこそが「関数」なのだ。&br; つまり「あらかじめ手順と渡すものを決めておくことで、規定された処理を行ってくれるもの」なのである。&br; &br; 関数を実際に見る前に「引数」と「戻り値」というものについて、上記の話にからめて知っていただこう。&br; 「引数(ひきすう)」とは「Aを頼む際には大きな書類2枚と小さな書類1枚を渡すよ」といった場合の、その書類である。&br; 関数を実行する際には「0個以上の引数」が必要である。これは関数を作成する際に取り決める。&br; 「戻り値(もどりち)」とは「仕事が終わったら、その完成品を渡してね」といった場合の、その完成品である。&br; 関数は「必ず1つの戻り値」を持つ。&br; &br; ---- ***作成と使用 それでは、実際に関数を作成し、使用する例を見てみよう&br; Scene.my.func1 := (var) => { var % 2 == 0 ? true : false }; Scene.my.x = Scene.my.func1(2); 1行目で関数を製作し、2行目で使用している。&br; 関数の内容としては「引数が偶数ならばtrue、奇数ならfalseを戻り値とする」である。&br; つまりは偶数か奇数かを判定するための関数だ。&br; &br; 関数の書式は以下のとおりである&br; 関数名 = ( 引数名 ) => { 処理内容 } -関数名はもちろん「Scene.my.」をつけることを忘れてはならない -引数は「0個以上」と定められているので、引数が必要ない関数ならば何も表記しなくてよい。 --引数は2つ以上でも構わなく、その場合は「,」で区切って宣言する。 -処理内容も2行以上でも構わない。その際はきっちり1行ごとに「;」で区切ること。 &br; 尚、関数の作成を行う際にはF11キーで現れるコンソール画面から作成する必要がある。&br; ちなみに、たとえその関数がonCollide内に書かれていても「e.other.○○」や「e.this.○○」などの変数は使用できない。&br; 関数内で使用したい値については基本的に引数で渡してやらねばならない。&br; ただし、Phun自体が持っている変数については使用することが出来る。(「Sim.○○」や「App.○○」など)&br; &br; 以下にいくつかの関数の作成例を示す&br; &br; -三角形の高さと幅を引数として渡すと、その面積を求める関数 (引数が2つある関数) ◇関数   scene.my.triangle := ( width , height ) => { width * height * 0.5 }; ◇使用例   scene.my.x = scene.my.triangle( 3.0 , 5.0 );   scene.my.x には 3.0 * 5.0 * 0.5 の演算結果 7.5 が入る。&br; &br; -シミュレーション経過時間0.5秒ごとに戻り値がtrueとfalseで入れ替わる関数 (引数を持たない関数) ◇関数   scene.my.blink := () => { sim.time % 1.0 >= 0.5 ? true : false }; ◇使用例 onCollide = (e) =>{   text = { "" + ( scene.my.blink ? "Yes" : "No" ) }; }   書かれた物質のtext属性値が0.5秒ごとに "Yes" と "No" 交互に変わる。&br; &br; ---- ***用意されている関数 あらかじめPhunのシステム上に作成されていて、使用可能な関数はいくつもある。&br; かなりの量であるが、実際に使用する可能性のあるものは限られる。&br; 使用頻度の高い関数をいくつか書き留めておこう。&br; &br; -数学関数 |CENTER:80|CENTER:180|CENTER:180|c |関数名|引数|戻り値| |math.asin(x)|浮動小数点型|逆三角関数 arcsin(x)の値| |math.acos(x)|浮動小数点型|逆三角関数 arccos(x)の値| |math.atan(x)|浮動小数点型|逆三角関数 arctan(x)の値| |math.sin(x)|浮動小数点型、単位は[rad]|三角関数 sin(x)の値| |math.cos(x)|浮動小数点型、単位は[rad]|三角関数 cos(x)の値| |math.tan(x)|浮動小数点型、単位は[rad]|三角関数 tan(x)の値| -Scene属関数(主に物質の生成) |CENTER:140|CENTER:80|CENTER:80|c |関数名|引数|戻り値| |scene.addBox{ x }|(後述)|"box"| |scene.addCircle{ x }|(後述)|"circle"| |scene.addFixjoint{ x }|(後述)|"fixjoint"| |scene.addHinge{ x }|(後述)|"hinge"| |scene.addPen{ x }|(後述)|"pen"| |scene.addPlane{ x }|(後述)|"plane"| |scene.addPolygon{ x }|(後述)|"polygon"| |scene.addSpring{ x }|(後述)|"spring"| |scene.addWater{ x }|(後述)|"water"| |scene.EraseWater|(なし)|(なし)| add****{}タイプの関数の引数については、[[phn形状について]]を参照にしてほしい。&br; というだけも味気ないので、2つの例を以下に挙げておく&br; &br; -位置[10.0,25.5]に、幅15.0 高さ20.0 密度10.0のboxを追加するスクリプト scene.addBox{ pos = [ 10.0 , 25.5 ]; size = [ 15.0 , 20.0 ]; density = 10.0 }; &br; -横長の長方形に、二つの丸をヒンジで接続するスクリプト scene.addBox{ pos = [ 0.0 , 0.0 ]; size = [ 6.0 , 2.0 ]; geomID = 100; }; scene.addCircle{ pos = [ 2.0 , -0.5 ]; radius = 0.8; geomID = 101 }; scene.addCircle{ pos = [-2.0 , -0.5 ]; radius = 0.8; geomID = 102 }; scene.addHinge{ geom0 = 100; geom0pos = [ 2.0 , -0.5 ]; geom1 = 101; geom1pos = [ 0.0 , 0.0 ] }; scene.addHinge{ geom0 = 100; geom0pos = [-2.0 , -0.5 ]; geom1 = 102; geom1pos = [ 0.0 , 0.0 ] }; &br; ※追記 Thymeで物体を発生させる場合、速度と角速度も指定できる。両方共に「じょうほう」メニューで表示されている単位(速度 m/s, 角速度 rad/s)で指定する。 -x速度20m/s、y速度10m/s、角速度30rad/sの円を発生させるスクリプト scene.addBox({vel := [20.0, 10.0]; angVel := 30}); &br ---- **§配列の応用 配列の解説部分で作った配列のような1列しかない配列は、1次元配列と言う。&br; 1次元という呼び名があるからには、2次元配列ももちろん存在する。&br; 作成の仕方と使用の仕方を以下に示す。&br; scene.my.x := [ [1,2,3] , [4,5,6] ]; これが2行3列の2次元配列である。&br; 配列の0番目の値として「要素3の配列」が入っており、1番目の値にも「要素3の配列」が入っている。&br; これを使用する際には以下のように書く&br; scene.my.y := scene.my.x(0)(1); scene.my.xの0行目の1番目を指定している。&br;この時scene.my.yに入る値は「2」である。&br; scene.my.xの内容を視覚的にわかりやすく表にまとめると、以下のようになる。&br; -scene.my.x(A)(B) |CENTER:50|CENTER:50|CENTER:50|CENTER:50|c |\|B=0|B=1|B=2| |A=0|1|2|3| |A=1|4|5|6| ちなみに、2次元配列を作る際に、列の値は必ずしも全て揃える必要はない。&br; 更に、データ型はそれぞれの要素ごとに記録されるため、揃える必要はない。(これは1次元配列でも同じく)&br; つまり、以下のような配列も生成可能である。&br; scene.my.x := [ [ 11 , 12 , 13 ],[ "welcome" , 2 , "phun"],[ 21 , 22 , 23 , 24 , 25 ] ]; scene.my.y := [ [ "one" , 2 , "three" ],"welcome",[ true , "or" , false ],[ "Let's" , "phun" ] ]; それぞれ内容は以下のようになる。 -scene.my.x(A)(B) |CENTER:70|CENTER:100|CENTER:100|CENTER:100|CENTER:100|CENTER:100|c |\|B=0|B=1|B=2|B=3|B=4| |A=0|11|12|13|(error)|(error)| |A=1|"welcome"|2|"phun"|(error)|(error)| |A=2|21|22|23|24|25| -scene.my.y(A)(B) |CENTER:70|CENTER:100|CENTER:100|CENTER:100|c |\|B=0|B=1|B=2| |A=0|"one"|2|"three"| |A=1|(error)|(error)|(error)| |A=2|true|"or"|false| |A=3|"Let's"|"phun"|error| -scene.my.x(1)(4) や scene.my.y(3)(2) など、表記が(error)のものは使用することが出来ない。 -scene.my.y の A=1の場合は、そこだけ1次元配列のままなので、"welcome" を参照したければ「scene.my.y(1)」と表記する。 &br; ---- *大きな間違いの訂正とお詫び  講座の書き出し時点で「ThymeスクリプトをonCollide属性以外にも書き込み可能だ」と書きましたが間違いであることが分かりました。&br; 書いたそのときは動きはすれど、Phunを終了させたりファイルに保存する際に、onCollide以外の属性に書いたスクリプトは保存されない&br; ことが多いという事実が判明しました。&br;  紛らわしい文章を載せてしまい、まことに申し訳ありませんでした。(現在は訂正済み)          2010/08/23 08:08 作成主 ---- *コメント欄 #pcomment(7)

表示オプション

横に並べて表示:
変化行の前後のみ表示:
ツールボックス

下から選んでください:

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