onEnterFrame で複数メソッドを個別に実行する方法

onEnterFrameとかのイベントで、複数のメソッドをダイナミックに実行するうまい方法がわかりませぬ。これはFlashを始めた頃から悩んでいることのひとつだったりして。

たとえば、徐々にアルファ値を上げていきながら、あるタイミング(フレーム)からスケールアップするとか。または、onEnterFrame 内で処理Aと処理Bを同時に実行するとき、onEnterFrame をdeleteするには、両方の処理が完了するのを待たなければならず、そのためにムダなif文が入ってしまうとか。

その場しのぎで色んな方法を試してきたけど、そろそろ汎用化できたら良いなーってことで、EventDispatcher を使う方法を試してみたよ。

まずは、サンプルケース。

class TestClass extends MovieClip {
	/**
	  * クリックされたらmethodAとmethodBを実行
	  */
	public function onPress():Void {
		this.onEnterFrame = function() {
			methodA();
			methodB();
		};
	}
	private function methodA():Void {
		if(this._x <= 100) {
			this._x += 10;
		}
	}
	private function methodB():Void {
		if(this._y <= 60) {
			this._y += 10;
		}
	}
}

本来であれば、methodAとmethodBの処理が両方とも終了した時点で、onEnterFrame を delete してしまいたいところ。各メソッドに終了状態を Boolean で返させて判断するとか、いろいろ策はありそうだけど、そういうのは「the その場しのぎ」でよろしくなさげ。methodC とか methodD とか、やることが増えてきた途端に、「マジめんどいわー」ってなる。

そこで EventDispatcher を使うと、以下のような感じ。

import mx.events.EventDispatcher;
class TestClass extends MovieClip {
	private var addEventListener:Function;
	private var removeEventListener:Function;
	private var dispatchQueue:Function;
	private var dispatchEvent:Function;
	/**
	  * コンストラクタ
	  */
	public function TestClass() {
		EventDispatcher.initialize(this);
	}
	/**
	  * クリックされたらmethodAとmethodBを実行
	  */
	public function onPress():Void {
		this.addEventListener("execute", methodA);
		this.addEventListener("execute", methodB);
		this.onEnterFrame = function() {
			if(this["__q_execute"].length > 0) {
				this.dispatchEvent({type:"execute"});
			} else {
				delete this.onEnterFrame;
			}
		}
	}
	private function methodA():Void {
		if(this._x <= 100) {
			this._x += 10;
		} else {
			this.removeEventListener("execute", methodA);
		}
	}
	private function methodB():Void {
		if(this._y <= 60) {
			this._y += 10;
		} else {
			this.removeEventListener("execute", methodB);
		}
	}
}

こうすると、各処理の終了状態を、それぞれのメソッド内部で完結できるので、イベント側でそれを意識する必要がなくなる。つまり、各メソッド間の状態管理がなくなって、処理の独立性が高まるという話。これで methodZ まで来ても怖くない。

上のコードだと実用性・有用性が伝わりづらいけど、MovieClip へのダイナミックな Strategy 交換の実現を考えるときには便利なはず。そうであって欲しい。うん。

ただ、これは mx.events.EventDispatcher を無理矢理つかおうとして、__q_execute とか flash内部の接頭辞をハードコーディングしているので、いただけないのは確か。うーむ。これを元に独自クラス化するのが素敵っぽい。

コレ系で良いアイデア持っている人、おせーてください。

このエントリーのトラックバックURL
http://www.deftrash.com/admin/mt4/mt-tb.cgi/300