ActionScript 3.0で始めるオブジェクト指向スクリプティング
第24回 インスタンスの管理と配列の並べ替え
前回の第23回「クラスのデザインとループ処理」では,EllipticMotionクラスのデザインを将来の拡張も考えて整理し,タイムラインのフレームアクションでは繰返し処理により複数のインスタンスを配置した(図1)。
今回の課題は,まずインスタンスの回転するスピードを,マウスポインタの位置によって変えることにする。つぎに,インスタンスの重ね順を,3次元風の表現に対応するよう修正しよう。
マウスポインタの位置に応じてインスタンスの回転スビードを変える
まずは,インスタンスが回転するスピードを,マウスポインタの位置によって変えるため,前回のスクリプト2で修正定義したEllipticMotionクラスにもう少し手を加えよう。
今のところ,インスタンスのアニメーションは,コンストラクタメソッドEllipticMotion()の本体で,インスタンスごとのDisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)にリスナー関数rotate()を登録して処理している。
public class EllipticMotion extends MovieClip {
// ...[中略]...
public function EllipticMotion(nDegree:Number, myCenter:Point, myRadius:Point) {
degree = nDegree;
center = myCenter;
radius = myRadius;
addEventListener(Event.ENTER_FRAME, rotate); // 後に削除
setRotation();
}
しかし,同じマウスポインタの座標値を,すべてのインスタンスからいちいち確かめるのは効率がよくない。また,のちにインスタンスの重ね順をコントロールする際には,それぞれの仮想の奥行きの値をメインタイムラインから調べる必要がある。
そうだとすれば,タイムラインに配置したインスタンスは,タイムラインのフレームアクションで管理することにしたい。そのうえで,EllipticMotionクラスのrotation()メソッドはタイムラインから呼出し,マウスポインタの座標に応じた回転角の値をその引数として渡そう。
Flashムービー(FLA)ファイルのフレームアクションとして作成した前回のスクリプト3には,タイムラインに配置するEllipticMotionインスタンスが納められるべき配列を新たに変数として宣言し,初期化する。そして,続くforループのコードブロック{}の中で,生成したインスタンスを表示リストに入れるとともに,この配列にも加えることにする。
var instances_array:Array = new Array(); // 追加: 配列を変数として宣言・初期化
for (var i:int = 0; i < nCount; i++) {
var _mc:EllipticMotion = new EllipticMotion(nDegree * i,myCenter,myRadius);
addChild(_mc);
instances_array.push(_mc); // 追加: 配列にインスタンスを加える
}
これで,タイムラインのフレームアクションで,いつでも配列 (instances_array)からEllipticMotionインスタンスが取出せる。つまり,そのインスタンスを参照して EllipticMotionクラスのrotation()メソッドが呼出せるようになった。そこで,新たな関数rotate()をフレームアクションに定義して,これをタイムラインのDisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)にリスナーとして登録しよう。
var deceleration:Number = 0.1;
// ...[中略]...
addEventListener(Event.ENTER_FRAME, rotate);
function rotate(EventObject:Event):void { // 追加: リスナー関数
var nSpeed:Number = (stage.mouseX - myCenter.x)*deceleration;
var nLength:uint = instances_array.length;
for (var i:int = 0; i<nLength; i++) {
var _mc:EllipticMotion = instances_array[i]; // インスタンスの取出し
_mc.rotate(nSpeed); // インスタンスのrotate()メソッドを呼出す
}
}
rotate()関数本体では,マウスポインタのステージ中央からの水平位置に応じた回転角(nSpeed)を求めたうえで,forループの処理によりEllipticMotionインスタンスを配列(instances_array)から順にすべて取出し,その回転角の値を各インスタンスのrotate()メソッドに渡して呼出している(※1)。
以上ふたつの修正を加えたフレームアクションが,次のスクリプト1だ。
スクリプト1 マウスポインタの中央からの水平位置に応じてインスタンスの回転スピードを変える
// タイムライン: メイン
var myCenter:Point = new Point(stage.stageWidth / 2, stage.stageHeight / 2);
var myRadius:Point = new Point(100, 50);
var nCount:uint = 6;
var nDegree:Number = 360 / nCount;
var instances_array:Array = new Array();
var deceleration:Number = 0.1;
for (var i:int = 0; i < nCount; i++) {
var _mc:EllipticMotion = new EllipticMotion(nDegree * i, myCenter, myRadius);
addChild(_mc);
instances_array.push(_mc);
}
addEventListener(Event.ENTER_FRAME, rotate);
function rotate(EventObject:Event):void {
var nSpeed:Number = (stage.mouseX - myCenter.x) * deceleration;
var nLength:uint = instances_array.length;
for (var i:int = 0; i < nLength; i++) {
var _mc:EllipticMotion = instances_array[i];
_mc.rotate(nSpeed);
}
}
- ※1
- マウスポインタのステージ中央からの水平位置に応じてアニメーションのスピードを変える処理については,第12回「マウスポインタとスクロールの連動」を参照してほしい。


