ActionScript 3.0では、EventDispatcherを使用してイベントをキャプチャできます。EventDispatcherを使用して独自のイベントを作成することもできます。この作業には、新規または既存のイベントの送り出し、新しいタイプのイベントの作成、イベントをリッスンするイベントハンドラに渡すインスタンスを持つ新しいEventクラスの定義(Eventクラスに基づく)が含まれます。
イベントを手動で送り出すには、EventDispatcherのdispatchEventメソッドを使用します。dispatchEventを呼び出すときは、送り出すイベントを記述したEventオブジェクトを渡します。このイベントは、すべての有効なターゲット(伝達される場合は複数)に伝わり、これらのターゲットにリスナーとして割り当てられているイベントハンドラが呼び出されます(その特定のタイプのイベントをリッスンしている場合)。ハンドラが呼び出されると、各ハンドラはdispatchEventに渡されるEventオブジェクトを受け取ります。
target.dispatchEvent(new Event("type"));
新しいイベントインスタンスは、typeパラメータと、オプションのbubblesパラメータおよびcancelableパラメータを指定して作成されます。デフォルトでは、少なくともEventクラスのbubblesパラメータとcancelableパラメータは、trueとして明示的に渡されない限り、falseになっています。MouseEventなどのEventクラスのサブクラスは、さらに多くのパラメータを受け取ります。MouseEventクラスの場合、bubblesのデフォルト設定はtrueです。MouseEventおよび他のEventクラスの使用について詳しくは、『ActionScript 3.0 リファレンスガイド』を参照してください。
独自のEventクラスを作成するには、コアのEventクラスを拡張します。これらのカスタムサブクラスは、独自のカスタムイベントの送り出しに使用でき、ユーザが選択した独自のプロパティがあります。ただし、Eventクラスを拡張する際は、デフォルトのメソッドを上書きし、独自のclone()メソッドを確実に実装できます。すべての状況で必要なわけではありませんが、cloneメソッドはイベントインスタンスをコピーするためにFlash内部で使用されることがあります。cloneメソッドによってクローン作成の対象となるイベントインスタンスの正確なコピーが作成されない場合は、エラーが発生します。
カスタムイベントは、Flash Player内で継承的に認識されないイベントを示す場合に役立ちます。独自のEventクラスを作成すると、カスタムイベントに関連する追加情報を指定して、これらのイベントのハンドラを用意できます。ここに示す例では、BounceEventカスタムクラスを使用します。このクラスはバウンスイベントとともに使用され、画面上のboxが画面の端でバウンスしたことを示します。
BounceEventクラスは、ActionScript 2.0のクラスと同様に、外部のActionScriptファイルで定義します。Eventクラスを拡張することで自動的に継承される通常のEventプロパティに加えて、BounceEventクラスにはsideプロパティがあり、バウンスしたオブジェクトが画面のどの端から発生したかを判断できます。
カスタムプロパティに加えて、イベントに使用する様々なタイプに対応するタイプ定数(MouseEvent.MOUSE_DOWNなど)をカスタムEventクラスに指定することをお勧めします。BounceEventクラスでは、BOUNCE定数に格納される、「bounce」という名前のイベントのタイプを使用します。クラス定義は次のとおりです。
package {
import flash.events.Event;
public class BounceEvent extends Event {
public static const BOUNCE:String = "bounce";
private var _side:String = "none";
public function get side():String {
return _side;
}
public function BounceEvent(type:String, side:String){
super(type, true);
_side = side;
}
public override function clone():Event {
return new BounceEvent(type, _side);
}
}
}
clone関数もBounceEvent定義に含まれていることに注目してください。返された値はBounceEventインスタンスであって、Eventインスタンスではありませんが、BounceEventはEventを拡張し、そのタイプがEventになるので許容されます(overrideは上書きする元のメソッドと同じ関数シグネチャを持つ必要があるので、clone関数の戻り型はEventである必要があります)。
これでこのクラスを使用して、boxがバウンスしたときに送り出されるイベントインスタンスを作成できます。バウンスイベントをリッスンしているイベントハンドラは、そのイベントに関連するBounceEventsを受け取ることができます。
四角形に、boxというインスタンス名を付けます。

図9.BounceEventクラスを使用した「box」という名前のムービークリップインスタンス
次のタイムラインスクリプトをフレーム1に追加します。
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var velocityX:Number = 5;
var velocityY:Number = 7;
var padding:Number = 10;
function bounceHandler(event:BounceEvent):void {
trace("Bounce on " + event.side + " side");
}
function moveBox(event:Event):void {
box.x += velocityX;
box.y += velocityY;
var limitLeft:Number = padding;
var limitRight:Number = stage.stageWidth - box.width - padding;
var limitTop:Number = padding;
var limitBottom:Number = stage.stageHeight - box.height - padding;
if (box.x <= limitLeft) {
velocityX = Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
}else if (box.x >= limitRight){
velocityX = -Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "right"));
}
if (box.y <= limitTop) {
velocityY = Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "top"));
}else if (box.y >= limitBottom){
velocityY = -Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "bottom"));
}
}
box.addEventListener(Event.ENTER_FRAME, moveBox);
addEventListener(BounceEvent.BOUNCE, bounceHandler);
次のMXMLを使用します。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="300" height="300"
applicationComplete="initApp()">
<mx:Script>
<![CDATA[
public var velocityX:Number = 5;
public var velocityY:Number = 7;
public var padding:Number = 10;
public function bounceHandler(event:BounceEvent):void {
trace("Bounce on " + event.side + " side");
}
public function moveBox(event:Event):void {
box.x += velocityX;
box.y += velocityY;
var limitLeft:Number = padding;
var limitRight:Number = stage.stageWidth - box.width - padding;
var limitTop:Number = padding;
var limitBottom:Number = stage.stageHeight - box.height - padding;
if (box.x <= limitLeft) {
velocityX = Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
}else if (box.x >= limitRight){
velocityX = -Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "right"));
}
if (box.y <= limitTop) {
velocityY = Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "top"));
}else if (box.y >= limitBottom){
velocityY = -Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "bottom"));
}
}
public function initApp():void {
box.addEventListener(Event.ENTER_FRAME, moveBox);
addEventListener(BounceEvent.BOUNCE, bounceHandler);
}
]]>
</mx:Script>
<mx:Canvas width="20" height="20" x="20" y="20" backgroundColor="#800000" id="box">
</mx:Canvas>
</mx:Application>
ムービーをテストしてみます。boxがstageの端でバウンスすると、次の出力が表示されます。
Bounce on bottom side Bounce on right side Bounce on top side Bounce on left side Bounce on bottom side ...
これは、各バウンスイベントでbounceHandlerイベントハンドラ関数が呼び出された結果です。dispatchEventメソッドを使用してboxインスタンスに新しい方向が指定されるたびに、moveBox関数(enter frameイベントのイベントハンドラ)内でバウンスイベントが送り出されます。例えば、次のコード行を見てみましょう。
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
この行は、新しいバウンスイベントをboxインスタンスからすべてのリスナーに送り出します。これらのリスナーは、渡されたEventオブジェクトのsideカスタムプロパティを使用して、バウンスした端が「左」であったことを判断できます。
イベントがboxから送り出されたものであっても、bounceHandler(boxインスタンスのリスナーではない)はイベントを受け取ることができます。これは、BounceEvent定義では、コンストラクタ内のsuper()の呼び出し(Eventコンストラクタを実行する)に、イベントのバブルを示す2番目の引数trueが指定されているためです。それによって、bounceHandlerがリッスンしていたもの(Flashではroot、Flexではapplication)も含め、boxのすべての親にイベントを渡す伝達が可能になります。