キーボード入力改

(サンプル一覧を表示する)

キーボード入力処理を、実用に耐える程度に修正してみました。

以前のものは、入力と同時に移動処理も行うようになっていましたが、
修正版では、入力処理と移動処理が別々になっています。
こうすることで、キーの自動リピート時間ごとにガクガクと動くのではなく、
スムーズに移動を行うことができます。

また、Flash 画面クリック時に、IME を無効化する処理も入れてあります。
日本語入力が ON になっていると、Flash 上でキー入力処理が取れないといった
トラブルが発生することがありますが、これを入れることで、
動かない時のユーザからの苦情を減らすことができますし、
なぜ動かないのかという問題の切り分けも少し簡単になります。
Flash の実行画面
キーボード入力改

Flashプレーヤーが入っていないか、JavaScriptが無効になっているようです。

Get Adobe Flash player

キーボード入力改

ソースコード

package 
{
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.ui.Keyboard;
	
	/**
	 * キーボード入力改
	 * @author Hikipuro
	 */
	public class Main extends Sprite 
	{
		/**
		 * 埋め込み画像
		 */
		[Embed(source='../image/test001.png')]
		private var image1:Class;
		
		/**
		 * 動かす画像
		 */
		private var bitmap:Bitmap;
		
		/**
		 * メッセージ表示用テキストフィールド
		 */
		private var textField:TextField;
		
		/**
		 * キー入力処理用オブジェクト
		 */
		private var keyInput:KeyInput;
		
		
		/**
		 * コンストラクタ
		 */
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		/**
		 * 初期化イベント
		 * @param	e
		 */
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			// キー入力処理用オブジェクトの準備
			keyInput = new KeyInput();
			addChild(keyInput);
			
			// キー入力を無効にするときは下のコードを呼び出す。
			// removeChild(keyInput);
			// 再び有効にするときは、addChild(keyInput); を呼び出す。
			
			// 画像の準備
			bitmap = Bitmap(new image1);
			bitmap.smoothing = true;
			bitmap.cacheAsBitmap = true;
			bitmap.x = 100;
			bitmap.y = 70;
			bitmap.scaleX = 2;
			bitmap.scaleY = 2;
			addChild(bitmap);
			
			// テキストフィールドの準備
			textField = new TextField();
			textField.autoSize = TextFieldAutoSize.LEFT;
			textField.x = 5;
			textField.y = 5;
			addChild(textField);
			
			// イベントの登録
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		/**
		 * キーが押された時のイベント
		 * @param	event
		 */
		private function onKeyDown(event:KeyboardEvent):void
		{
			// テキストフィールド更新
			switch (event.keyCode) 
			{
				case Keyboard.LEFT:
					textField.text = "左キーが押されました";
					break;
				case Keyboard.RIGHT:
					textField.text = "右キーが押されました";
					break;
				case Keyboard.UP:
					textField.text = "上キーが押されました";
					break;
				case Keyboard.DOWN:
					textField.text = "下キーが押されました";
					break;
			}
		}
		
		/**
		 * キーが離された時のイベント
		 * @param	event
		 */
		private function onKeyUp(event:KeyboardEvent):void
		{
			// テキストフィールド更新
			switch (event.keyCode) 
			{
				case Keyboard.LEFT:
					textField.text = "左キーが離されました";
					break;
				case Keyboard.RIGHT:
					textField.text = "右キーが離されました";
					break;
				case Keyboard.UP:
					textField.text = "上キーが離されました";
					break;
				case Keyboard.DOWN:
					textField.text = "下キーが離されました";
					break;
			}
		}
		
		/**
		 * フレーム開始イベント
		 * @param	event
		 */
		private function onEnterFrame(event:Event):void 
		{
			// - キーが押されっぱなしになっているかチェック
			//   keyInput.isKeyHeld(Keyboard.LEFT);
			//
			// - キーが押された直後かチェック
			//   keyInput.isKeyDown(Keyboard.LEFT);
			//
			// - キーが離された直後かチェック
			//   keyInput.isKeyUp(Keyboard.LEFT);
			
			
			// キー入力状態に応じて、画像を移動させる
			if (keyInput.isKeyHeld(Keyboard.LEFT))
				bitmap.x -= 5;
			else if (keyInput.isKeyHeld(Keyboard.RIGHT))
				bitmap.x += 5;
			
			if (keyInput.isKeyHeld(Keyboard.UP))
				bitmap.y -= 5;
			else if (keyInput.isKeyHeld(Keyboard.DOWN))
				bitmap.y += 5;
			
			// キー入力情報を更新
			// 必ず ENTER_FRAME イベントの最後に呼び出す
			keyInput.refresh();
		}
		
	}
}

/**
 * キー入力処理用クラス
 */
class KeyInput extends flash.display.Sprite
{
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.system.IME;
	
	/**
	 * キー定数の最大値
	 * 数が多いほど処理時間がかかる。
	 */
	private const MAX_KEYCODE:int = 256;
	
	/**
	 * キー入力状態保存用変数
	 */
	private var keys:Array;
	
	/**
	 * 1 フレーム前の
	 * キー入力状態保存用変数
	 */
	private var prevKeys:Array;
	
	/**
	 * コンストラクタ
	 */
	public function KeyInput():void 
	{
		// キー入力状態保存用変数の初期化
		// キー定数の最大値が収まるくらい作っておけば問題ないかと思って
		// 256 にしています。
		keys = new Array();
		prevKeys = new Array();
		for (var i:int = 0; i < MAX_KEYCODE; i++) {
			keys.push(new Boolean());
			prevKeys.push(new Boolean());
		}
		
		// イベントの登録
		// addChild(), removeChild() に応じて、
		// 自動的に必要なイベントハンドラを登録・削除する
		addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		addEventListener(Event.REMOVED_FROM_STAGE, onRemoveFromStage);
	}
	
	/**
	 * キー入力情報を更新
	 * 必ず ENTER_FRAME イベントの最後に呼び出す
	 */
	public function refresh():void 
	{
		// 1 フレーム前のキーを保存して、次のフレームの開始時に比較することで
		// 押し始め、押し終わりを検出する
		for (var i:int = 0; i < MAX_KEYCODE; i++)
			prevKeys[i] = keys[i];
	}
	
	/**
	 * キーが押されっぱなしになっているかチェック
	 * @param	keycode	Keyboard クラスのキー定数
	 * @return	押されている時 True
	 */
	public function isKeyHeld(keycode:uint):Boolean
	{
		return keys[keycode];
	}
	
	/**
	 * キーが押された直後かチェック
	 * @param	keycode	Keyboard クラスのキー定数
	 * @return	押され始めて最初のフレームの時 True
	 */
	public function isKeyDown(keycode:uint):Boolean 
	{
		if (keys[keycode] == true && prevKeys[keycode] == false)
			return true;
		return false;
	}
	
	/**
	 * キーが離された直後かチェック
	 * @param	keycode	Keyboard クラスのキー定数
	 * @return	離された最初のフレームの時 True
	 */
	public function isKeyUp(keycode:uint):Boolean 
	{
		if (keys[keycode] == false && prevKeys[keycode] == true)
			return true;
		return false;
	}
	
	/**
	 * addChild() された時に呼ばれるイベント
	 * @param	event
	 */
	private function onAddedToStage(event:Event):void 
	{
		trace("KeyInput.onAddedToStage");
		// ステージ上のイベントの登録
		// キー入力とマウス入力はステージに登録する
		stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
		stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
	}
	
	/**
	 * removeChild() された時に呼ばれるイベント
	 * @param	event
	 */
	private function onRemoveFromStage(event:Event):void 
	{
		trace("KeyInput.onRemoveFromStage");
		
		// キー入力を全て OFF にする
		for (var i:int = 0; i < MAX_KEYCODE; i++) {
			keys[i] = false;
			prevKeys[i] = false;
		}
		
		// 登録したイベントを解除する
		stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
		stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
	}
	
	/**
	 * ステージ上でマウスが押された時のイベント
	 * @param	e
	 */
	private function onMouseDown(event:MouseEvent):void 
	{
		// IME を無効にする。
		// 環境によっては IME 無効処理時に例外が発生するので、例外をスルーする
		try { IME.enabled = false; }
		catch (e:Error) { ; }
	}
	
	/**
	 * キーが押された時のイベント
	 * @param	event
	 */
	private function onKeyDown(event:KeyboardEvent):void
	{
		// 入力 ON
		keys[event.keyCode] = true;
	}
	
	/**
	 * キーが離された時のイベント
	 * @param	event
	 */
	private function onKeyUp(event:KeyboardEvent):void
	{
		// 入力 OFF
		keys[event.keyCode] = false;
	}
}
		

参照

外部リンク