スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

DXRubyで成長曲線と父母遺伝の再現、描写

こんにちはーれゆーですーっ



(まちがったみれいゆーだ)


今日は DXRuby Advent Calender 2014 の10日目という事で、私が担当します!!

前回は、Vivit_jc さんの 「〜ゲーム制作者だってテストがしたい!〜DXRubyユーザー向けRspec入門」でした!!
まだ記事は続きがあるようで・・・楽しみですね!!
さて、今回は、DXRubyで成長曲線と父母遺伝の再現、描写
となっておりますっ。これは私が遺伝子計算を勉強した中で得た計算式の詳細や、その曲線を描写する為の処理、他様々に加え、父と母のグラフを定義して合成するといった内容を行います!
(あまりDXRubyに関係が無いかもしれませんがご了承くださいすいません><)


使用するパロメータを定義する
今回成長曲線を描く上で必要になってくる要素を遺伝子生物学から考えていきましょう。
まず、人間にも、いかなる生物にもそうですが、思春期ありますよねー。この思春期の時には体、そして心も急成長します。これを第二次性徴期といいます。今回はこの第二次性徴期を再現しようと思います。最も成長する歳を名づけて成長頂点歳、変数は
peakage
としましょう。
只、性徴期が訪れた時、人によってその成長の進み具合、言い換えれば傾斜が違うと思います。人間同士ならわかりにくいですが特にネズミとゾウを比べるとはっきりわかります。この時必要となってくる要素を、私は成長幅と名付けます。
今回変数表すとこれは
peakrange
となります。
でも、人間もそうですが、皆さん寿命が存在します。この定められた寿命を超える、体力が衰え、もう体を成長させようにも出来ないことになります。これを決定づける値、ここでは変数で
activeage
とします。
最後に、皆さん体を成長させるとき、それには二つの方法が存在すると思います。それは、体が自然に成長していく「自然成長」と、ジムなどによって人為的に鍛えて成長させる「訓練成長」です。
これも今回は再現しようと思います。変数はそれぞれ、
naturalpower
trainpower
としましょう。
尚、上記二つの成長力を総合して
totalpower
とします。




成長曲線グラフを考える

さてグラフの時間となりました!
まず、今回の成長曲線を描くにおいての必要な動きの四大要素を掲示します!!
A:成長頂点歳に向けて指数関数的に成長力が上昇する事
B:成長幅の広さに応じてその成長力の傾斜をゆるめ、成長力最大値を可変する。
C:成長頂点歳を過ぎた場合一定の成長力に収まる
D:寿命を超えると成長力が0に進む。。


これらを叶える為に必要な計算式を順々に取り出して行きましょう!

A:成長頂点歳に向けて指数関数的に成長力が上昇する事
まずこれは、成長頂点歳の時には成長力が最大になるということの再現を行います。

Rubyでは指数関数を扱うモジュール/メソッドとして Mathモジュールの expメソッドがあります!
(組み込みライブラリ)

よって単純に表したい場合こうなります。

grow = Math.exp(time)


timeは0..60 つまり現在の年齢を指定します。 grow に出力されます。
これが成長頂点歳の場合、

peakgrow = Math.exp(peakage)


となります。

B:成長幅の広さに応じてその成長力の傾斜をゆるめ、成長力最大値を可変する。
これを表現する為に、二箇所の計算式を加える必要が出てきます。
まずは成長力の傾斜をゆるめこれに着目します。
確かに最大の値はA:で述べた成長頂点歳式peakgrowに達したいけどそこまでの傾斜を決めたい場合、必要なメソッドは、そう、 Math.sinです。
この三角関数Sin(正弦関数)の持つ値は、角度にして0..180と言われており、そのグラフは、
○の上半円を切り取ったようなものとなります。
角度ではなくラジアンで表現した場合、その単位はπとなりますが、πをrubyではMath::PIで取得する事ができます。
そして、以上の三角関数式に影響したい値は、ここまでの流れから当然、成長幅、peakrangeとなります。
以上を纏めると入る式は、

Math.sin(peakrange * Math::PI/ 180.0)



次に、成長力最大値を可変するに着目します。
成長力の最大値を決めるにあたって、必ず「成長頂点歳と成長幅によって"大きく"総合成長力を変えない」という事を前提に置きます。
ここの"大きく"と表現した理由は、人間誰しもが同じ成長力を持ってそれが早熟であれ晩成であれ同じだとすると、特に晩成は「報われない」からです。今回はこの事も視野に入れた式を作ります。
こうして作りたい式は、
「成長歳が遅ければ晩成として成長力の総合が大きい」
「成長幅が成長歳と釣り合っていればさらに成長力の総合が大きい」

これを再現する為、得た式はこうなります。

((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * time))


最早自分でも意味の分からない式となりました。

C:成長頂点歳を過ぎた場合一定の成長力に収まる
前述の式は成長頂点歳に向かうまでの再現をとりました。次は成長頂点歳を過ぎた場合の式を作ります。
マイナスの方向に進む式の為、まず、最大成長力から引く式を立てます。

peakgrow - 式



さて、次に考えるのは、最大成長力からの「減衰力」です。
すなわち、成長頂点歳を境にマイナス式を大きくするという考えで行くので、加える式は

式 * (time - peakage )


さあこれで再現しよう!という時に問題が一つあります。それは、
「減衰が無い。」
この状況を回避する為に「成長頂点歳を過ぎたら約半分程の成長力を残そう」
という考えです。これを考慮して完成した2式がこちらです。

grow = ((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * time)) if time <= peakage and time <= activeage
peakgrow = ((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * peakage))
grow = peakgrow - (((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * (time - peakage )))) / 2.0 if time > peakage and time <= activeage



型崩れが激しいです。申し訳ございません。この上記にある条件式は双方とも、「寿命を超えていない」事を書いております。さて、超えるとどうなるのか・・・・

D:寿命を超えると成長力が0に進む。。
先ほどに書いた式の減衰に、小幅な修正を加えます。すなわち、先ほどは値を"2"としたことで減衰したら残りの成長力は成長頂点歳に比べ"1/2"で安定しました。ならば、値が2より大きく、そして∞に向かうなら・・・

/ (2.0 * (activeage / time) ** 4.0)


尚、** は累乗を意味します。

こうして成長曲線を描く3式が出来上がりました。列挙すると、


for time in 0..60
grow = ((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * time)) if time <= peakage and time <= activeage
peakgrow = ((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * peakage))
grow = peakgrow - (((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * (time - peakage )))) / 2.0 if time > peakage and time <= activeage
grow = peakgrow - ((totalpower / peakage ) / peakrange) / (1.0 + peakage * Math.exp(-1.0 * (Math.sin(peakrange * Math::PI/ 180.0)) * (time - peakage ))) / (2.0 * (activeage / time) ** 4.0) if time > activeage
grow = 0.0 if grow <= 0.0
totalgrow += grow
end



後ほど完成されたコードは pastebinにあるのでご心配なく!!




成長曲線グラフを描写する。

Window.draw_font(10 + time * 10 , (-1 * grow* 100) + 440 , "●" , font,hash={color: [255,66,66]})


これを前述のFOR文に加えます。
ここで、-1 が入ってる理由は、Windowのy座標は大きければ↓に向かうからです。今回は上に山なりとするため、440をベースに-1 * としました。
年齢が1進むことでx座標は10進みます。

こうして、完成されたグラフはこう映ります。

grarh4.png

赤が自然成長力のみ、水色が訓練成長力のみ、黄色が総合成長力です。
また後の話にはなりますが、分かりやすいように左上に各重要値の配列を表示しています。
ここでは左から順に、
自然成長力、訓練成長力、成長頂点歳、成長幅、成長寿命、生命寿命。
成長寿命の事を今までは単純に寿命と言ってきました。実際の遺伝ゲームとなると生命寿命を別に設け、その歳に死亡するようにします。




おまけ?父母遺伝を書く。

この項は最早おまけです。
一つ言うならば、父と母で引き継ぐ"比率"が重要という事ですね。
あとは、新しい子を人間の配列に pushします。




こうして、すべてのコードを導入した完成品をpastebinに貼ったのでどうぞ!!!

http://pastebin.com/CdVGVjzt




grarh1.png
grarh2.png
grarh3.png

最後までご視聴ありがとうございました!!
さて、次回は、unohanaTさんの記事です。お楽しみにーーー
スポンサーサイト

コメント

コメントの投稿

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。