サムネールを水平に並べてスクロールさせるメニューのインターフェイスがある(図1)。スクロールする方向やスピードは、マウスポインタの位置によって変わる。今回と次回の2回にわたって、このようなMovieClipのアニメーションをつくってみたい。今回のポイントは、条件を判定して分岐する処理の書き方だ。
ループする水平スクロール―ifステートメント
まずは、これまでの復習として、毎フレーム5ピクセルで水平方向右に単純にスクロールするMovieClipのフレームアクションを書いてみよう(スクリプト1)。スクリプトを書くときは、いきなり目的の動作を実現しようとするのでなく、処理を小分けにして段階的に進めていくことが大切だ。
上級者でも、ひとつのミスもなく、1回で動きを完成することはたやすくない。小分けにして作成と確認を繰返していけば、問題が出たときも、その調査対象を限定できる。事件の早期解決には、何より容疑者の絞り込みが重要なのだ。
毎フレームの描画更新は、DisplayObject.enterFrame
イベントで受取る。MovieClipインスタンスにこのイベントのリスナー関数を登録して、関数内では初期値として定めたピクセル数をインスタンスのDisplayObject.x
プロパティに代入している(図2)。このアニメーションの処理については、これ以上説明の必要はあるまい。
次は、ステージ右端を超えたら、左端にループしてスクロールを続ける処理だ。インスタンスの水平座標がステージ右端を超えたかどうかの条件を判定する必要がある。ここで、if
ステートメントを使う。シンタックスは、次のとおりだ。
今回の条件は、インスタンスのDisplayObject.x
プロパティの値が、ステージ右端の座標値つまりStage.stageWidth
を超えたかどうかである。
この条件を表す式は、数学の時間に習った不等式と同じく、不等号(<
、>
)で表す。等しい場合を含めるときは、等号を右に添える(<=
、>=
)。注意しなければならないのは、両辺の値が等しいこと(等価)を示すには、等価演算子(==
)が用いられることだ。ActionScriptでは、等号(=
)は代入の演算子として区別される。
MovieClipインスタンスの水平座標がステージ右端を超え、if
条件が満たされたなら、インスタンスを左端に移動する。ステージ左端の水平座標は、もちろん0である。すると、条件判定のif
ステートメントは、次のように記述すればよさそうに思える。
実際、[ムーピープレビュー]を確かめると、ステージ右端を超えたインスタンスは、また左端から現れてスクロールを続ける(図3)。アニメーションが、インスタンスひとつであれば、差支えはないかもしれない。しかし、並べてスクロールすると、問題が明らかになる。
なぜなら、ステージ右端からはみ出すピクセル数は、インスタンスによって最小1ピクセルから最大5ピクセルまで異なる可能性がある(図4)。そのピクセル数に関係なく、インスタンスをステージ左端の水平座標0に移動すると、インスタンス同士の間隔が変わってしまう。つまり、ステージ右端を1ピクセルだけ超えて0ピクセルに移動したインスタンスは、5ピクセル超えてようやく0ピクセルにループしたインスタンスより4ピクセル早く進むことができ、後続のインスタンスとは間隔が開いてしまうのである。
インスタンスの間隔を変えないためには、一律に同じ座標に移すのではなく、一定の距離左に移動すればよい。つまり、水平座標からステージ幅を差引くのである。現在値から数値を差引くときは、演算子-=を用いる。
前述スクリプト1にこの条件判定の処理を加えたのが、以下のスクリプト2である。
マウスポインタの位置でスクロール方向を変える―else/else ifステートメント
次は、マウスポインタの位置によって、MovieClipインスタンスのスクロールする方向を変えてみる。ポインタの位置がステージ中央より左寄りならインスタンスを右にスクロール、そうでなければ左にスクロールするように処理を書き加えよう。ここでまた条件判定が必要だ。
今回は条件を満たす場合と満たさない場合、それぞれにやるべきことがある。条件を満たさない場合の処理は、以下のようにelse
ステートメントで追加する。条件を満たすかどうか調べることは、条件を「評価」するという。そして、if
条件が満たされると、ActionScriptは評価の結果として、条件の式をtrue
という値に変換する。そして、条件が満たされなければ、評価の結果はfalse
になる。
マウスポインタの座標は、DisplayObject.mouseX
/DisplayObject.mouseY
で調べられた。ただし、ステージから見た座標が知りたいので、ターゲットはStageオブジェクトにする必要がある。移動方向の変更は、移動ピクセル数の符号をプラスマイナスで切替えればよい(スクリプト3)。移動ピクセル数の値を変化させるのは、次回の課題とする。
まず、ステージの水平座標中央の値は、変数nStageCenterとして設定した。この値を計算するとき、ステージ両端の座標を引き算するのでなく、足して平均を取ることに注意しよう。
次に、そのステージの水平座標中央の値とステージから見たマウスポインタのx座標値とを比べる。マウスポインタの座標の方が小さければ、if
条件はtrue
と評価され、移動方向は右方向つまり移動ピクセル数をプラスのnSpeedとする。条件の評価がfalse
なら、移動方向は左で移動ピクセル数はマイナスのnSpeedになる。これらの値は、ローカル変数nNewSpeedに格納する。
あとは、変数nNewSpeedの値をインスタンスのDisplayObject.x
プロパティに設定すれば、マウスポインタの位置に応じて水平スクロール方向が切替わる。[ムービープレビュー]で動きを確認してみよう(図5)。
スクリプト3で気になるのは、インスタンスがステージ左端を超えたとき、右端にループしないことだ。そこで、条件判定をさらに加えて、ループする処理を組込むことにする。
ステージ右端を超えたら左端にループするif
ステートメントはすでに記述してある。これにelse
ステートメントを書き足したのでは、意図する処理にならない。インスタンスがステージの領域内をアニメーションしていて、ループしなくてよい場合まで含んでしまうからだ。さらに条件を追加して、インスタンスがステージ左端の外に移動した場合にループさせたい。このように条件を加えるとき使うのがelse if
ステートメントである。
else if
ステートメントはいくつでも追加できるので、何段階もの条件を設定して、それぞれについて処理を記述することも可能だ。また、else
ステートメントは、不要なら書かなくてよい。すると、インスタンスが左端を超えたら右端にループする処理は、前のフレームアクション(スクリプト3)に追加すると、次のスクリプト4のようになる。
これで、インスタンスが左右どちらの端を超えても、反対の端にループしてスクロールを続けるようになった。次回は、ステージの水平方向中央からマウスポインタが離れるほど、速くスクロールさせる処理を加えて、スクリプトのアニメーションを完成させる。
今回解説した次のサンプルファイルがダウンロードできます。