キーボード入力処理を、実用に耐える程度に修正してみました。
以前のものは、入力と同時に移動処理も行うようになっていましたが、
修正版では、入力処理と移動処理が別々になっています。
こうすることで、キーの自動リピート時間ごとにガクガクと動くのではなく、
スムーズに移動を行うことができます。
また、Flash 画面クリック時に、IME を無効化する処理も入れてあります。
日本語入力が ON になっていると、Flash 上でキー入力処理が取れないといった
トラブルが発生することがありますが、これを入れることで、
動かない時のユーザからの苦情を減らすことができますし、
なぜ動かないのかという問題の切り分けも少し簡単になります。
Flash の実行画面
|
キーボード入力改
|
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;
}
}