[AS3] キーボードのキー操作をVectorオブジェクトで扱う [Edit]

キーボードのキー操作を扱うふたつの手法」では、タイムラインに配置したMovieClipインスタンス(my_mc)を、キーボードの矢印キーで上下左右に動かしてみました(再掲図001)。この同じお題をVectorクラスで整えてみましょう。

図001■ タイムラインに配置したMovieClipインスタンスを矢印キーで上下左右に動かす(再掲)
AS3_OptimizingPerformance_01_02_008.png

01 キーコードをインデックスとしてVectorインスタンスに操作の情報を与える

矢印キーのキーコードは37〜40です(gihyo.jp「ActionScript 3.0で始めるオブジェクト指向スクリプティング」第13回「キーボードによる操作」p.2の表2「Keyboardクラスの矢印キーの定数」参照)。しかし、Vectorインスタンスのエレメントは、0から始まる連番の整数でなければなりません。つまり、新たなデフォルトのVectorインスタンスには、配列と違って、いきなりインデックス37にエレメントが加えられないのです。

けれど、長さを定めたVectorインスタンスはつくれます。そして、キーボードのキーにはかぎりがあります。したがって、十分な長さのVectorインスタンスをつくれば、矢印キーのキーコード番号にエレメントが納められます。以下のスクリプト001は、前出「キーボードのキー操作を扱うふたつの手法」のスクリプト002の配列をVectorインスタンスに置換えました。実質的に書替えたのは1行目のみで、あとは変数名を形式的に変えただけです。

スクリプト001■Vectorオブジェクトのキーコードに設定した操作情報でインスタンスを動かす
var operations:Vector.<Array> = new Vector.<Array>(300, true);
operations[Keyboard.LEFT] = ["x", -1];
operations[Keyboard.RIGHT] = ["x", 1];
operations[Keyboard.UP] = ["y", -1];
operations[Keyboard.DOWN] = ["y", 1];
stage.addEventListener(KeyboardEvent.KEY_DOWN, useVector);
function useVector(eventObject:KeyboardEvent):void {
	var operation_array:Array = operations[eventObject.keyCode];
	if (operation_array) {
		var property_str:String = operation_array[0];
		var pixels:Number = operation_array[1];
		my_mc[property_str] += pixels;
	}
}

このように配列をVectorインスタンスに変えただけで、処理は速くなります。前出「キーボードのキー操作を扱うふたつの手法」でご紹介した条件判定を使うスクリプト001と比べても、速さは見劣りしません。

02 クラスに定めたメソッドの参照によりインスタンスを操作する

前掲スクリプト001からさらに速さを求めるなら、動かすインスタンスのプロパティを配列アクセス[]で参照していることが見直されるべきでしょう。プロパティ名の文字列に配列アクセス演算子[]を用いたのでは、強い参照にならないからです(Adobeデベロッパーセンター「ActionScript 3.0におけるパフォーマンス向上のヒント」01「データ型を指定する」参照)。

そこで、インスタンスを動かすためのクラス(Operation)を定義します(スクリプト002)。コンストラクタメソッドには動かすインスタンスの参照を引数に与え、ふたつのメソッド(Operation.moveX()またはOperation.moveY())で水平もしくは垂直に動かします。

スクリプト002■インスタンスを動かすクラスの定義
package {
	import flash.display.MovieClip;
	public class Operation {
		private var target:MovieClip;
		public function Operation(myTarget:MovieClip) {
			target = myTarget;
		}
		public function moveX(nPixels:Number):void {
			target.x += nPixels;
		}
		public function moveY(nPixels:Number):void {
			target.y += nPixels;
		}
	}
}

フレームアクションは、以下のようにカスタムクラス(Operation)のインスタンスをつくり、そのメソッドの参照と引数に渡す値を入れ子の配列にしてVectorオブジェクト(operations)のエレメントに加えます(スクリプト003)。キーイベントのリスナー関数(useVector())は、Vectorオブジェクトからエレメントの入れ子配列を取出し、そのインデックス0のメソッドにインデックス1の引数を渡して呼出します。

スクリプト003■Vectorオブジェクトのキーコードに設定したクラスのメソッドでインスタンスを動かす
var operations:Vector.<Array> = new Vector.<Array>(300, true);
var myOperation:Operation = new Operation(my_mc);
operations[Keyboard.LEFT] = [myOperation.moveX, -1];
operations[Keyboard.RIGHT] = [myOperation.moveX, 1];
operations[Keyboard.UP] = [myOperation.moveY, -1];
operations[Keyboard.DOWN] = [myOperation.moveY, 1];
stage.addEventListener(KeyboardEvent.KEY_DOWN, useVector);
function useVector(eventObject:KeyboardEvent):void {
	var operation_array:Array = operations[eventObject.keyCode];
	if (operation_array) {
		var xMove:Function = operation_array[0];
		var pixels:Number = operation_array[1];
		xMove(pixels);
	}
}

前掲スクリプト001が配列アクセス[]で文字列のプロパティを操作するのに比べて、このスクリプト003はメソッドの参照(Function型)に引数を渡して呼出すため、扱いは速くなります。また、メソッドであれば、より込入った処理を定義することもできるでしょう。

ご参考までに、Vectorオブジェクトのエレメントにメソッドの参照を納めた場合と、前出「キーボードのキー操作を扱うふたつの手法」のスクリプト001のように条件判定で切り分ける場合とを比べてみました。

Evaluating key codes with switch statement vs a Vector 2 - wonderfl build flash online

コメント

この記事にコメントを書く

記事に対するテクニカルな質問はご遠慮ください(利用規約)。

その他の記事