まずはじめに、デベロッパーのみなさんにお知らせです。タイムラインは、デベロッパーさんの敵ではありません。むしろ、友達と言っていいくらいです。協力者です。ぜひとも、タイムラインを使いましょう。
デベロッパーの方々は、「アートワークをステージに配置するときは、ダイナミックに配置した方がタイムラインも整理できるのでよい」と教わっているのではないでしょうか。もっともらしく聞こえますが、実際はというと、みなさんが思っているほど役立つ教えではありません。
この記事ではプレローダーを作りますが、私はプレローダーを直接ステージに配置しています。その理由は、ダイナミックに配置する場合はディスプレイ領域の中心を計算しなければなりませんが、その手間が省けるからです。「x = width * stageWidth/2 + someOffset」といったコードを書く必要はありません。私の代わりにFlashが計算をしてくれるので、その分、私はプレローダーを自分の思い通りの位置に配置することに集中できます
プレローダーをステージの中心に配置し、プレローダーのタイムラインを図1のように作成してフレームラベルを付けました。

図1. プレローダーのタイムライン。各セクションにはフレームラベルを付けています
タイムラインだけでなく、さらにフレームラベルも付けました。その理由は、フレームラベルを使えば、アニメーションの内容が一目瞭然となるからです。「フレーム2で登場してきて、フレーム37で消え始める」といった内容をいちいちメモしておかなくても、フレームラベルの「IN」と「OUT」という文字を見れば、そのアニメーション内容がわかります。
タイムラインを活用すれば、ステージ上でプレローダーを表示する際の位置が思い通りにならずに試行錯誤することはありません。しかも、デザイナーがプレローダーを修正したい場合でも、簡単に行うことができます。INのラベルを付けた部分のアニメーションに10フレーム分追加したくなったとしても、問題ありません。さらにプレローダーの色をグリーンからパープルにしたい? もちろん大丈夫です。見た目をワイングラスにして、ローディングが進むごとにグラスが満たされるようにしたい? どうぞ、できますよ。つまり、タイムラインを使えば、「コンテンツのプレローディング」というプレローダーの本質的な機能を損なわずに、ルック&フィールを自由に変更することができるのです。
この記事で作成するプレローダーは、いろいろな状況に対応でき簡単に使い回しができるようにするため、以下のように設計しました。
わりと分かりやすい設計です。ただ、いつINやOUTのアニメーションが完了したのかをどうやって調べるのか気になる人もいるでしょう。それについては、次の項目で解説します。
ActionScript 3.0ではイベントディスパッチ(イベント送出)という概念があります。ActionScript 1.0や2.0の経験がある人ならば、十分に理解していなくても、なんとなく分かるのではいないでしょうか。たとえば、以下のようなコードがあります。
var mouseListener = new Object();
mouseListener.onMouseDown = function() {
trace("The mouse button is down.");
};
Mouse.addListener(mouseListener);
mouseListenerオブジェクトは、Mouseクラスのイベント(onMouseDown)を監視しています。そのイベント、つまりユーザーがマウスボタンを押したときに、MouseクラスはonMouseDownイベントをディスパッチ(送出)します。そして、mouseListenerオブジェクトがonMouseDown関数を実行します。イベントディスパッチの特長は、複数のオブジェクトが同じ1つのイベントを監視しつつ、そのイベントが起きたときにオブジェクトごとに異なる処理を設定できるというところにあります。以下のコードは、その例です。
var mouseListener1 = new Object();
var mouseListener2 = new Object();
mouseListener1.onMouseDown = function() {
trace("the mouse button is down.");
};
mouseListener2.onMouseDown = function() {
trace("1+1=" + (1+1));
};
Mouse.addListener(mouseListener1);
Mouse.addListener(mouseListener2);
2 つのリスナーがあります。2つのリスナーとも同じイベントを監視していますが、そのイベントが起きた際は異なる処理を行うようになっています。上記の例では、両方のリスナーとも出力パネルに違うメッセージをトレース出力しています。もちろんまったく異なる処理を実行させることも可能です。
オブジェクト指向プログラミングを習得したい、特にクラス作成に興味があるという人は、このイベントディスパッチ概念は非常に重要なものなので、ぜひ押さえておいてください。クラスの内容に関係なく、複数のクラスが同じイベントを扱うことができるのです。
先ほどオブジェクト指向プログミラングについて触れましたが、少し実際のコードから離れて、現実の世界に置き換えて考えてみましょう。あなたのコードはファーストフードレストラン「ActionScriptカフェ」だとします。そして、ユーザーは、そこに来るお客さんでお腹がすいています。お客さんが何かを注文したい。そのとき、あなたのレストラン(ActionScriptコード)での対応は、以下の2つが考えられます。
これをプログラミングに置き換えると、シナリオ1は古いスタイルのプログラミング方法です。どの時点で何が起きているのかが把握しづらく、バグがあっても解決するのが困難です。シナリオ2は理想的なプログラミング方法です。料理に問題があればクッククラスを調べればよく、レジに問題があればレジ係クラスを調べればいいのです。もし両方に問題があれば、タッチスクリーンクラスを調べるのです。とにかく、このように役割分担を明確にすることで、コードは整理され管理しやすくなります。
それでは、プレローダーを例に、ActionScript 3.0でイベントがどのように作用するかを説明しましょう。ActionScript 3.0では、独自のイベントを定義できます(ActionScript 2.0でも同様に行えます)。さらに、ムービークリップはEvent Dispatcherを拡張します。つまり、先ほどのコード例と同じ方法でムービークリップはイベントをディスパッチすることができます。この特徴がいかに役立つことなのかを、プレローダーを例にお見せしましょう。再度図1を見てください。タイムラインのIN_IDLEフレームラベルのところにコードがあります。
import com.bigspaceship.events.AnimationEvent; dispatchEvent(new AnimationEvent(AnimationEvent.ANIMATE_IN)); stop();
importステートメントは、外部クラス(後述します)をこのタイムラインで使用するために読み込むためのコードです。AnimationEventは私が作ったカスタムイベントで、ここではAnimationEvent.ANIMATE_INイベントをディスパッチします。このイベントの内容はシンプルです。 ActionScript 1.0でonMouseDown イベントが起きることによって「マウスが押された」ことが検知できるのと同じように、リスナーは、AnimationEvent.ANIMATE_INを監視し、「タイムラインのINフレームラベルのアニメーションが完了した」こと検知します。タイムラインのOUT_IDLEフレームラベルにも似たようなコードを記述しています。
import com.bigspaceship.events.AnimationEvent; dispatchEvent(new AnimationEvent(AnimationEvent.ANIMATE_OUT)); stop();
同じようにdispatchEventを使って、「タイムラインのOUTフレームラベルのアニメーションが完了した」ことをディスパッチしています。私は、これらのイベントを「イベントフック」と呼んでいます。INやOUTのアニメーションが再生されているとき、コードでは待機して監視しているのです。そしてイベントフックに到達すると、プレローディングを進めるようにロジックを作っています。イベントハンドリングの詳細については、Introduction
to event handling in ActionScript 3.0を見てください。