前回つくったマウスポインタに合わせて弾けるスプライトアニメーションに、さらにふたつ表現を加えたい。第1は、アニメーションの残像に、落ちる動きのぼかしを加える。いわゆる「モーションブラー」だ。第2に、ステージの下端まで落ちたインスタンスを弾ませる。簡単な物理の考え方を採入れる。
CreateJSがアップデートされた
先にお伝えしたいのは、CreateJSが2013年9月25日付でアップデートされたことだ。EaselJSは、0.6.1から0.7.0にマイナーバージョンが上がった。今回から早速新たなライブラリを使うことにしよう。すると、script要素に読込むEaselJSライブラリのJavaScriptファイルは差替えなければならない。
また、前回のスクリプトで用いたクラスBitmapAnimationの名前が、EaselJS 0.7.0からSpriteに変わる。今回のJavaScriptコードでは、新たなクラス名に書替える(後掲コード1参照)。
そしてもうひとつ、SpriteSheet()コンストラクタに渡す引数のオブジェクト(data)で、アニメーションの速さを決めるプロパティが変わる。これまでのfrequencyは、Ticker.tick「イベントいくつごとにひとコマ進めるかを定め」た(第12回「スプライトシートでアニメーションをつくる」の「SpriteSheetとBitmapAnimationクラス」参照)。これがspeedプロパティに改められ、デフォルトの何倍速で進めるのかという数値を与える。具体的には、frequencyの逆数(1 / frequency)となり、数値は大きいほどアニメーションが速くなる(後掲コード1参照)。
アニメーションの残像にモーションブラーを加える
まずは、アニメーションの残像にモーションブラーを加えよう(図1)。ただ厳密にいうと、CreateJSにモーションブラーのぼかし機能はない。ぼかし幅が水平と垂直それぞれに定められるので、垂直方向のぼかしを強くしてそれらしく見せる。
ぼかしの前に、残像をどうつくるかというと、これはプロパティひとつで定められる。Stage.autoClearというプロパティがそれだ。デフォルト値はtrueで、ステージを描き替える前にCanvasにあるものは自動的に消される。プロパティをfalseにすると、古い描画が残ったまま重ね描きされる。つまり、残像ができることになる(図2)。
では、残像のモーションブラーに移ろう。Canvasに直接残像を描いたことから想像がつくように、ぼかしはCanvasに掛ける。オブジェクトをひとつひとつぼかしていたら負荷が高い。とはいえ、Canvas全体をぼかすのも決して軽くはない。ぼかした残像を加えたアニメーションは、大きくつぎの3つの手順で進める。
- Canvasの残像にモーションブラーを加える。
- Canvasをアルファが加わった背景色で塗る。
- マウスポインタの動きに合わせた新たなインスタンスを加える。
第1に、残像の描かれたCanvas全体に、EaselJSのフィルタでモーションブラーを加える。第2に、Canvas全体をアルファが加わった背景色で塗る。Canvasに同じ大きさの半透明のシートを重ねる感覚だ(図3)。そうすると、古い残像ほどアルファつき背景色が塗り重ねられて消えてゆく。そのうえで、最後にマウスポインタの動きに合わせた新たなインスタンスを加えればよい。
使うメソッドを確かめていこう。まず、ぼかしについては、第8回「ぼかしフィルタとアルファマスク」の「BoxBlurFilterクラスで画像イメージをぼかす」で解説した。ただし、EaselJS 0.7.0でクラス名がBlurFilterに変わる。引数の定め方は同じだ。前述のとおり、垂直方向のぼかしを強める。また、オブジェクトひとつひとつが小さいアニメーションなので、ぼかし品質は低くして負荷を下げる。
つぎに、ぼかしはCanvasに加える。その場合、canvas要素からコンテキストという描画のオブジェクトを得る。そのメソッドがgetContext()だ。メソッドの引数は、取出すコンテキストを定める識別子の文字列である。2次元の描画は"2d"を渡せばよい[1]。
CanvasはCreateJSのオブジェクトではないので、DisplayObject.filtersプロパティは使えない。だが、BlurFilterクラスには、Canvasの2Dコンテキストにフィルタを掛けるBlurFilter.applyFilter()メソッドが備わっている。第1引数が2Dコンテキスト、後の4引数は適用する矩形領域を与える。
これで道具立ては整った。前回でき上がった第12回コード2「マウスポインタの動く座標につくられたスプライトアニメーションがランダムな方向に落ちる」に、JavaScriptコードを書き加えていこう。初期設定の関数(initialize())では、getContext()メソッドで2Dコンテキストの参照を変数(context)にとっておく。そして、Stage.autoClearプロパティはfalseに定めて残像を重ねる。
Canvasの残像をぼかしつつ背景色で消してゆく処理は新たな関数(fadeAndBlur())で定め、アニメーションの関数(animate())から呼出す。CanvasはBlurFilter.applyFilter()メソッドで垂直方向を強めにぼかす。BlurFilterインスタンスは使い回せるので、予め変数(blurFilter)に入れておいた。そして、背景色でCanvasを塗るのは、CreateJSでなくCanvasのプロパティおよびメソッドを用いた。fillStyleプロパティでアルファ(0.2)つきの塗り色(0xFFFFFF)を定め、fillRect()メソッドは与えられた矩形領域をその色で塗る(詳しくは、「<canvas>要素で定めた領域に図形を描く」をお読みいただきたい)。
これでマウスポインタに合わせて落ちるオブジェクトのアニメーションに残像が重なり、モーションブラーも加わる(前掲図1参照)。書替えたスクリプト全体は、つぎのコード1のとおりだ。
EaselJS 0.7.0について、もう少し補っておく。このバージョンのコンパクト版JavaScript(JS)ファイルeaseljs-0.7.0.min.jsには、フィルタのクラスも含まれるようになった。そのため、フィルタクラスのJSファイルをひとつひとつ読込まないでよい。また、BlurFilterになって、パフォーマンスも上がったという。
オブジェクトをステージ下端で弾ませる
オブジェクトがステージの下端まで落ちたら、上に弾ませたい。考え方は簡単で、垂直方向の速度(velocityY)を逆転つまり-1を乗じればよい。また、ステージ下端を超えて下がってしまった垂直座標は、その分上に持ち上げる。手を加えるのは、アニメーションの関数(animate())だ。
まず、前掲コード1では、オブジェクトがステージ下端座標(stageHeight)を超えたら、Stageオブジェクトの表示リストから除くことにしている。この条件は外す。替わりに、水平座標が両端の外に出たことを新たな条件に加えよう。オブジェクトがつぎに移る水平座標は変数(newX)にとっておく。
つぎに、オブジェクトの垂直座標がステージ下端を超えたら弾ませる。垂直方向の速度(velocityY)を逆転するとともに、少し勢いが衰えるよう-0.8を乗じた。ステージ下端をはみ出た垂直位置の大きさは、ステージの高さ(stageHeight)との剰余をとる。その大きさだけ、垂直位置をステージ下端から持ち上げればよい。その後のオブジェクトを落とす処理は基本的に変わらない。
これで、落ちたオブジェクトは、ステージ下端で弾むアニメーションになる(図4)。残像のモーションブラーも加わった。今回のお題が目指した表現はひとまずでき上がった。スクリプト全体は以下のコード2のとおりだ。
jsdo.itにもサンプルコードを掲げた。スプライトアニメーションを数多くつくったうえ、残像やぼかしを加えたので、予告したとおり重い動きになった。EaselJS 0.7.0でBlurFilterクラスのパフォーマンスが上がったとはいえ、もう少し動きを軽くできないだろうか。次回はそのあたりについて解説しよう。