分123今回からは,つぎのお題に取り組む。多角形の頂点を結んだかたちが,放物線状に落ちてきて,弾力のある動き方をする。それぞれの頂点の間の力のかかり方や,それらが弾むときの方向,他の頂点への力の変化など,かなり複雑な計算が求められるように感じるだろう。実は四則演算を使った簡単な式で,このアニメーションはつくられている。クラスでつくった点を放物線状に落とす第24回「マウスポインタの動きに弾みがついた曲線を滑らかに描く」では,「⁠オイラー法」という考え方にもとづき,バネのような動きを加速度と速度の四則演算で表した(⁠「⁠バネのような動きを数学の目で確かめる」参照⁠)⁠。速度を位置に足し込めば,新たな位置が求められる。速度も変わるなら,加速度を加えて新たな速度が導けた。今回のアニメーションも,やはり近似計算で式を簡単にする。オイラー法と異なるのは,時系列の位置座標を使って運動が表されることだ。「⁠ベレ法」と呼ばれ,動きが座標間の関係を示す四則演算で導けてしまう。アニメーションするかたちは点からつくられる。その点をクラス(VerletPoint)として定めよう。クラスのつくり方については,第17回「簡単なクラスを定義する」をご参照いただきたい。いつもの解説とは少し進め方を変えて,いきなりクラスのプロパティとメソッドの役割および働きを決めることにする。y:オブジェクトの現在のxy座標。_oldY:オブジェクトの前のxy座標。y):コンストラクタ。xy座標値を引数に渡す。update():オブジェクトの座標のプロパティ値を,速度にもとづいて更新する。constrain(rect):引数にRectangleオブジェクトを受取って,オブジェクトの座標をその矩形領域内に収める。getVelocity():オブジェクトの新旧xy座標から速度を求めて返す。render(graphics):引数に受取ったGraphicsオブジェクトに,オブジェクトの現行xy座標の点を描く。y):引数に受取ったxyピクセル値を,オブジェクトのxy座標に加える。点のクラス(VerletPoint)は以下のコード1のように定めた。このクラスをどう使ってアニメーションにつなげるのかは別にして,上の説明と照らし合わせれば,プロパティとメソッドひとつひとつが何をしているのかはほぼおわかりいただけるだろう。それらを簡単に説明していこう。コンストラクタVerletPoint()の引数にはインスタンスのxy座標値を渡して,その値が新旧xy座標のプロパティに初期値として与えられる。インスタンスを動かせば,今の座標とその前の座標が,それぞれのプロパティに定められることになる。update()メソッドは,インスタンスを動かしてプロパティの値を改める。動かすための速度はgetVelocity()メソッドが,古い座標と新しい座標の差から導いてPointオブジェクトで返す。そのため,このクラスは速度をプロパティにもたない。速度(ベクトル)のxy座標値をaddCoordinates()メソッドでオブジェクトの座標に加えて,新旧座標のプロパティが更新される。constrain()メソッドは,オブジェクトの座標を引数のRectangleオブジェクトが示す矩形領域の中に収める。Canvasの矩形領域を引数のRectangleオブジェクトとして与えれば,アニメーションする点はその領域の外に出ることはない。render()メソッドは,黒点を引数のGraphicsオブジェクトに描く。描画を消すGraphics.clear()メソッドやステージ再描画のStage.update()メソッドは呼んでいない。後々多くの点や線を描くため,これらのメソッドはクラスの外でまとめて呼び出したほうがよいからだ。y;};このクラス(VerletPoint)でつくったひとつの黒点を放物線状に落としてみよう(図1⁠)⁠。script要素に書いたJavaScriptは以下のコード1のとおりだ。いつものお約束どおり,初期化の関数(initialize())はbody要素のonload属性で呼び出す。黒点が放物線状に落ちる初期化の関数(initialize())は,ステージに描画用のShapeオブジェクト(shape)を加え,そのGraphicsオブジェクトを変数(drawingGraphics)にとった。Canvasの矩形領域をRectangleオブジェクトに与えて変数に納める(_stageRect⁠)⁠。そのうえで,コード1のクラス(VerletPoint)からつくったオブジェクトを変数(_point)に入れ,x座標値を動かした。アニメーションは,Ticker.tickイベントに加えたリスナー関数(draw())で扱う。アニメーションのリスナー関数(draw())がまず呼び出すのは,この後説明する点を動かす関数(updatePoint())だ。描画のGraphicsオブジェクトをクリアしてから,点のオブジェクト(_point)のrender()メソッドで新たな点を描く。点を動かす関数(updatePoint())は,点のオブジェクト(_point)のy座標を動かしてオブジェクトのupdate()メソッドで更新した後,動く範囲をconstrain()メソッドでCanvasの矩形領域(_stageRect)に納めた。_point.constrain(_stageRect);}実際の動きを確かめた方がよいので,jsdo.itに前掲コード1およびコード2を掲げた。コード1のクラス定義は[HTML]の欄に分けて書いている。見ると,何の変哲もないアニメーションだ。黒い点が,放物線状に落ちる。弾ませる処理は加えていないため,Canvas下端に落ちると,そのまま滑って右端で止まる。前掲コード2と動きをよく見比べると,ある特徴に気づく。点のオブジェクト(_point)のx座標を動かしたのは,初期設定の関数(initialize())の中で1度きりだ。それでも水平方向に動き続けるのは,点のクラス(VerletPoint())が速度をgetVelocity()メソッドにより,前の座標と今の座標の差で捉えているためだ。点のクラスのオブジェクトは,ひとたび動かせば,そのまま放っておいても同じ向きに動き続ける仕組みになっている。アニメーションのリスナー関数(draw())からは,点を動かす関数(updatePoint())が呼び出された。その関数が呼び出されるたびに,点のオブジェクト(_point)のy座標に一定の値を加えている。その結果,垂直方向には重力がかかったような動きになった。点のオブジェクトの座標を動かすことは,今の動きにさらに力を加えるのに等しいといえる(※1⁠)⁠。※1つまり,点のオブジェクトの位置座標を動かすのは,力つまり加速度を加えるのに等しい。位置に足し込む値なので,細かいことはいわず,変数名には速度(velocity)という語を用いた。