前回は、ランダムに動く粒子それぞれの間にバネのような力を与えてアニメーションさせた。すると、粒子は互いに集まっては離れることを繰り返す、という面白い動きになった(再掲第6回図3)。ここまでのコードは、以下のjsdo.itに掲げてある(第6回コード2)。
オブジェクトが引合う力の範囲をかぎる
互いに離れれば離れるほど、引き戻す力は強まるというのがバネの性質だ。ただし、それを単純に当てはめたために、仲間から外れた粒子の激しい動きが止められず、しかも仲間はずれは次第に増えてしまうというのが前回の問題だった。
もともと、バネはいくらでも伸び縮みするものではない。むしろ、その動きを正しく保てる範囲はかぎられる。そこで、この粒子のアニメーションでも、互いの間に引合う力が及ぶ距離を決めてしまおう。2点の座標からその間の距離を導くには、三平方の定理を用いる(図1)。2点の水平・垂直の各座標の差をそれぞれ2乗し、足し合わせてから平方根を求めればよい。
そこで、以下のように力の働く最大距離を変数(limit)で定める。そして、オブジェクト間にバネの力を加える関数(spring())の中で、その距離より近いオブジェクト同士だけ引合うようにする。
水平・垂直それぞれの座標の差(distanceXとdistanceY)は、もともと求めていた。だから、それぞれを2乗して(squareXとsquareY)加え、平方根を計算すれば、距離(distance)が導ける。平方根はMath.sqrt()メソッドで求まる。なお、累乗にはMath.pow()メソッドが使える。だが、Mathクラスの演算は遅くなりがちだ。2乗くらいなら、同じ値を2度掛けたほうが速い。
さて、処理の速さを考えるなら、もう一歩踏み込みたい。オブジェクト間の距離を条件に、互いに引合うかどうかを決めた。けれども、距離(distance)の値そのものは計算に使っていない。単に、if条件であらかじめ定めた制限値(limit)と比べただけだ。そうであれば、平方根など求めることはない。比べる制限値の方を2乗しておく。これで、またひとつ計算が減り、Mathクラスのメソッドも使わずに済んだ。
書き直したJavaScript全体は、以下のコード1のとおりだ。仲間から大きく外れると力が加えられなくなり、近づけば引き戻される。激しくやんちゃな動きをする粒子はめっきり減るはずだ(図2)。
引合うオブジェクト同士の直線で結んでみる
つぎは、引合う力が働いているオブジェクト同士を線で結んでみよう。その下ごしらえとして、線を描くためのオブジェクトをステージに置く。つぎのように、Shapeオブジェクト(background)をつくって、Stageオブジェクトの子に加えた。また、粒子や線の色が変えやすいように、カラー値は変数(colorInt)に定めた。なお、Graphicsオブジェクトに描画するときの色は文字列で定めるため、カラー値を静的メソッドGraphics.getRGB()で変換する。
線の描画は、以下のようにTicker.tickイベントのリスナー関数(move())から始める。描画用のオブジェクト(background)については、まず前のイベントのとき描かれた線をGraphics.clear()メソッドで消しておかなければならない。
線は力の働くオブジェクトの間に引くので、引合う力を計算する関数(spring())の仕事になる。ふたつのオブジェクトの座標は力の計算と線描に使うため、変数(_0x、_0y、_1x、_1y)にとっておく。そして、力が働くかどうかif条件で確かめた後、新たに定める線描の関数(drawLine())を呼出す。この関数(drawLine())は、線の太さと色、2点のxy座標という引数にもとづいて直線を描く。
これで、引合う力が働くオブジェクト同士が直線で結ばれる(図3)。JavaScript全体をまとめたのが以下のコード2だ。線が加わることで、アニメーションの表現が有機的になった。ただ、直線が強すぎて粒子は見えにくくなってしまった。
オブジェクトが離れるほど線を薄くする
粒子を見やすくするには、直線を細くするかアルファでも掛ければよい。だが、もう一歩進めて、オブジェクトが離れるほどアルファを下げてみよう。
すると改めて、ふたつのオブジェクトの距離を求めることになる。そこで、以下のように、まず力の働く最大距離を変数(max)にとった。そして、引き合うかどうかのif条件は平方(2乗)のまま比べ、線で結ぶことになってから平方根で距離(distance)を求める。無駄な計算は避けるためだ。
アルファは、Graphics.getRGB()メソッドの第2引数で定める。オブジェクト同士がくっついたら1、最大の距離(max)で0になるように比率を定めた。
これで、オブジェクト同士が離れるほど、結ばれる直線は薄くなり、最大距離で線は消える。オブジェクトが引合う力は距離に比例させているので、アルファが見た目で示していることにもなる。JavaScriptの全体は、以下のコード3のとおりだ。
「Node Garden」のお題はでき上がりだ。jsdo.itでは背景は黒くして、粒子と線を白で描いた。このアニメーションも長く再生していると、粒子の動きはかなり激しくなる。それを避けるには、パラメータを調整してもよいし、簡単なのは制限速度を設けることだろう。これらは、読者のみなさんそれぞれがお試しいただきたい。次回から、また新たなお題に取組む。