7分マウスポインタの位置に応じてインスタンスの回転スビードを変えるインスタンスの重ね順を管理する前回の第23回「クラスのデザインとループ処理」では、EllipticMotionクラスのデザインを将来の拡張も考えて整理し、タイムラインのフレームアクションでは繰返し処理により複数のインスタンスを配置した(図1⁠)⁠。複数のインスタンスが楕円軌道でアニメーションする今回の課題は、まずインスタンスの回転するスピードを、マウスポインタの位置によって変えることにする。つぎに、インスタンスの重ね順を、3次元風の表現に対応するよう修正しよう。インスタンスの重ね順が3次元風の表現に一部対応していないマウスポインタの位置に応じてインスタンスの回転スビードを変えるまずは、インスタンスが回転するスピードを、マウスポインタの位置によって変えるため、前回のスクリプト2で修正定義したEllipticMotionクラスにもう少し手を加えよう。今のところ、インスタンスのアニメーションは、コンストラクタメソッドEllipticMotion()の本体で、インスタンスごとのDisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)にリスナー関数rotate()を登録して処理している。setRotation();}しかし、同じマウスポインタの座標値を、すべてのインスタンスからいちいち確かめるのは効率がよくない。のちにインスタンスの重ね順をコントロールする際には、それぞれの仮想の奥行きの値をメインタイムラインから調べる必要がある。すれば、タイムラインに配置したインスタンスは、タイムラインのフレームアクションで管理することにしたい。そのうえで、EllipticMotionクラスのrotation()メソッドはタイムラインから呼出し、マウスポインタの座標に応じた回転角の値をその引数として渡そう。Flashムービー(FLA)ファイルのフレームアクションとして作成した前回のスクリプト3には、タイムラインに配置するEllipticMotionインスタンスが納められるべき配列を新たに変数として宣言し、初期化する。続くforループのコードブロック{}の中で、生成したインスタンスを表示リストに入れるとともに、この配列にも加えることにする。(instances_array)からEllipticMotionインスタンスが取出せる。EllipticMotionクラスのrotation()メソッドが呼出せるようになった。そこで、新たな関数rotate()をフレームアクションに定義して、これをタイムラインのDisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)にリスナーとして登録しよう。}}rotate()関数本体では、マウスポインタのステージ中央からの水平位置に応じた回転角(nSpeed)を求めたうえで、forループの処理によりEllipticMotionインスタンスを配列(instances_array)から順にすべて取出し、その回転角の値を各インスタンスのrotate()メソッドに渡して呼出している[1]⁠。以上ふたつの修正を加えたフレームアクションが、次のスクリプト1だ。}}[1]マウスポインタのステージ中央からの水平位置に応じてアニメーションのスピードを変える処理については、第12回「マウスポインタとスクロールの連動」を参照してほしい。この変更にともなって、EllipticMotionクラスにも大きくふたつ修正を加える必要がある。触れたとおり、EllipticMotionクラスのコンストラクタメソッドにおけるDisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)へのリスナー登録を削除することだ。メソッドが、引数として回転するスピードを受取るようにしなければならない。メソッドはもはやリスナー関数ではなくなるので、引数にイベントオブジェクトは受取らない。替わりに、フレームアクションから渡される回転角の数値を引数とするのである。degreeに設定する。タイムラインから呼出すには、rotate()メソッドのアクセス制御の属性はpublicで指定する必要がある。}以上のふたつの修正を加えたのが、次のスクリプト2である。これでメソッドrotate()はリスナー関数ではなくなり、メインタイムラインから呼出せるようになった。インスタンスプロパティとして宣言されていたフレーム当たりの回転角speedは、もはや不要なので削除した。}}[ムービープレビュー]を試すと、マウスポインタのステージ中央からの水平位置によって、インスタンスの回転する方向と速さが変わる(図3⁠)⁠。マウスポインタのステージ中央からの水平位置により回転の方向とスピードが変わるインスタンスの重ね順を管理するインスタンスの重ね順を3次元風の表現に合わせて変えるには、まずインスタンスを正しい重ね順に並べ替える必要がある。メインタイムラインのフレームアクション(スクリプト1)では、EllipticMotionインスタンスを配列に納めた。幸いなことに、配列は並べ替えのメソッドArray.sort()を備えている。このメソッドは、以下のように引数なしで配列に対して呼出せる。trace()関数による[出力]の結果を見ると、エレメントの整数が昇順に並べ替えられている。0,1,2,3,4このArray.sort()メソッドには、ふたつ注意がある。1つは、並べ替えた結果の配列が返されるのではなく、参照した配列そのもののエレメントの順序が変わる。1つは、その並べ替えの順序はデフォルトでは、文字列のように頭からひと桁ずつ比較したうえで決められる。つぎのスクリプトの結果を見てほしい。0,1000,200,30,4Array.sort()メソッドには、引数として比較関数が指定できる。比較関数というのは、エレメントの並べ替えの順序を指定する関数だ。比較関数を定義すれば、配列エレメントの並べ順は自由に決められる。ふたつの引数の比較評価の結果を数値で返す}Array.sort()メソッドに比較関数を指定すると、メソッドが配列エレメントを並べ替えるとき、エレメントをふたつずつ取出してはその関数には引数として渡す。比較関数は、そのふたつの引数のエレメントの大小、つまり並べ順を評価して、その結果を次表1のような数値として返す。1たとえば、数値のエレメントを数値として比べて並べ替えるには、比較関数(compare)をつぎのように定義したうえで、Array.sort()メソッドの引数に指定すればよい。trace()関数の[出力]結果を見ると、今度は数値の小さい順に並べ替えられたことが確かめられる。0,4,30,200,1000ところで、Array.sort()メソッドの引数には、次表2のようなArray定数も指定できる。数値の小さい順に並べ替えるのであれば、Array.sort()メソッドの引数に定数Array.NUMERICを指定する方がたやすい[2]⁠。英字の大文字小文字を区別せずに並べ替える。並べ替えの順序を、降順(大きい順)に指定する。エレメントが数値の配列を、その値の大きさで順序づける。ターゲットの配列は変更せず、並べ替えた結果の整数インデックスをエレメントとした配列が返される。エレメントに重複がない配列のみを並べ替える。重複があれば、0を返す。[2]ふたつ以上のArray定数を同時に指定することもできる。その場合は、ビット単位の論理和演算子|を用いて、指定したい定数の論理和をとって、Array.sort()の引数として渡す。引数をつぎのように定数で指定すると、エレメントは数値で降順に並べ替えられる。本題に戻って、EllipticMotionインスタンスの重ね順の処理を考えよう。インスタンスの仮想3次元の奥行きは、getIndexZ()メソッドで調べられた。(⁠instances_array)に入ったインスタンスの順序を、インスタンスに対するgetIndexZ()メソッドの戻り値で並べ替える。そのための比較関数compare()の定義は、次のようになる。}}仮想3次元の奥行きの順に配列(instances_array)内のEllipticMotionインスタンスを並べ替えても、まだ実際の表示上の重ね順には反映されない。EllipticMotionインスタンスの表示リスト内の順序を、この配列内の新たな並べ順に合わせる必要がある。表示リスト内におけるインスタンスのインデックスの位置を変えるのは、DisplayObjectContainer.setChildIndex()メソッドだ。つぎのシンタックスで、親(DisplayObjectContainer)インスタンスの表示リストに含まれている子のDisplayObjectインスタンスを、指定したインデックスに移動する。setOrder()を定義する。EllipticMotionインスタンスを、仮想3次元の奥行きの順に並べ替える。つぎに、EllipticMotionインスタンスの表示リスト内の順序を、配列instances_arrayのエレメントの順序に合わせてDisplayObjectContainer.setChildIndex()メソッドにより設定している。}}以上、2つの関数を追加したフレームアクションが、次のスクリプト2だ。関数setOrder()の呼出しは、DisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)のリスナー関数rotate()の最後に加えている。EllipticMotionクラスのgetIndexZ()が「アクセスできないメソッド」であるという[コンパイルエラー]が表示される(図4⁠)⁠。これは、フレームアクションに定義した関数compare()からインスタンスのgetIndexZ()メソッドを呼出している、次の2行のステートメントに対するエラーだ。メソッドにアクセスできない旨を伝える[コンパイルエラー]これは前掲スクリプト2でEllipticMotionクラスのrotate()メソッドについて、そのアクセス制御の属性を修正したのと同じ理由だ。スクリプト2では、getIndexZ()メソッドにはprivate属性が指定されている。タイムラインのフレームアクションからメソッドを呼出すには、アクセス制御の属性としてつぎのようにpublicを指定しなければならない。EllipticMotionクラスの定義全体を再掲することは控えよう。サンプルファイルをダウンロードして確かめてほしい。今度は[ムービープレビュー]がエラーなく行え、インスタンスの重ね順もつねに仮想3次元の奥行きに合わせて表示される(図5⁠)⁠。仮想3次元の奥行きに応じてインスタンスの重ね順が設定される今回解説した次のサンプルファイルがダウンロードできます。Ltd.ページ内容の全部あるいは一部を無断で利用することを禁止します⁠。個別にライセンスが設定されている記事等はそのライセンスに従います。