書き物

技術とか作った物の話とか愚痴文句感想など

ゲームを作るとき取得できると便利かもしれないキー入力状況情報パターン

まえがき

キーボードを使うゲームは、当然キー入力の状況を受け取らないといけません。

どのキーが押されているか、押されていないか等。


Aキーが押されているか、押されていないかだけでなく、

もうちょっといろんなパターンでのキー入力状況を簡単に取得できるようにしておくと、

いちいちaddEventLisならなくて良いので便利です。


パターン1 - 押されているか、押されていないか

一番スタンダードなキー入力の情報です。

Aキーを押しているならtrue、押されていないならfalseを取得できます。

package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
/**
    * キー状態
    */
public class KeyState extends Sprite
{
private var _aKey:Boolean;     // Aキー
/** Aキー */
public function get aKey():Boolean { return _aKey; }
/**
        * コンストラクタ
        */
public function KeyState()
{
_aKey = false;
addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
/**
        * キーダウンイベント処理
        * 
        * @param event イベント
        */
private function onKeyDown(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case 90:
_aKey = true;
break;
default:
break;
}
}
/**
        * キーアップイベント処理
        * 
        * @param event イベント
        */
private function onKeyUp(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case 90:
_aKey    = false;
break;
default:
break;
}
}
}
}

パターン2 - KEY_DOWNイベントっぽく

メニューをキーボードで操作して、項目を選択するような場合、

パターン1だと目的の項目へ選択カーソルをやるのに苦労します。

例えば↓キーを押した場合、わずかに長押ししただけでカーソルは下へガーっと行きすぎてしまったり。

通常こういう場合はKEY_DOWNイベントをaddEventLisなるものですが、

いちいちイベントイベントするのが面倒なので、

変数を参照するだけでこのキー入力状況を取得できるようにしようと思います。

package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
/**
    * キー状態
    */
public class KeyState extends Sprite
{
private var _sysAKey:Boolean;  // システム用Aキー
/** システム用Aキー */
public function get sysAKey():Boolean { return _sysAKey; }
/**
        * コンストラクタ
        */
public function KeyState()
{
_sysAKey = false;
addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
/**
        * システム用キー初期化
        *  全体処理の最後で実行する
        */
public function initSystemKey():void
{
_sysAKey = false;
}
/**
        * キーダウンイベント処理
        * 
        * @param event イベント
        */
private function onKeyDown(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case 90:
_sysAKey = true;
break;
default:
break;
}
}
/**
        * キーアップイベント処理
        * 
        * @param event イベント
        */
private function onKeyUp(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case 90:
_sysAKey = false;
break;
default:
break;
}
}
}
}

initSystemKeyメソッドを処理の最後に呼び出すようにすれば、

ほぼKEY_DOWNイベントっぽいキー入力状況を取得できます。

private var _keyState:KeyState; // キー状態
/**
 * エンターフレームイベント処理
 * 
 * @param event イベント
 */
private function onEnterFrame(event:Event):void
{
exec(); // メインの処理
_keyState.initSystemKey(); // 処理の最後に実行
}

パターン1との違いは以下のような感じ。

パターン1  パターン2  キー状況
true       true       ←Aキー押す(以下押しっぱなし)
true       false
true       false
true       false
true       false
true       true
true       true
false      false      ←Aキー離す
false      false
false      false
false      false
false      false
false      false

厳密にキー入力状況を取得したい場合は当然KEY_DOWNイベントを使うしかないですが、

そうでない場合は楽じゃないかと。


パターン3 - キー押しっぱなし状況

Aキーを2フレーム以上押しっぱなしにしている場合true、そうでない場合falseを取得します。


どこで使うかというと、例えばアクションゲームの場合。

ジャンプを↑キーでする場合、押しっぱなしの判定をしなければ↑キーを押しっぱなしにすることで、

地上に降りるたびに自動的にジャンプしてしまいます。

その場その場で「↑キーを離さなかったならジャンプしない」という処理を入れるのは、結構しんどいです。(相当しんどい)

ジャンプだけでなく、攻撃動作しかり、使いどころはたくさんあります。


以下のソースのKeyStateクラスはパターン1のものです。

以下のクラスはキー入力の状況ではなく、ゲーム内の各物体が持っている操作用のキー情報です。

Aキーを押したとき、KeyStateクラスを介してこのクラス内の攻撃キー変数にtrue,falseを設定することで、

その物体の攻撃キーを押した場合のふるまい等をさせます。

package
{
/**
    * オブジェクトのキー状態
    */
public class ObjectKeyState
{
private var _attackKey:Boolean;         // 攻撃キー
private var _attackKeyKeepFlg:Boolean;  // 攻撃キー押しっぱなしならtrue
/** 攻撃キー */
public function get attackKey():Boolean { return _attackKey; }
/** 攻撃キー押しっぱなしフラグ */
public function get attackKeyKeepFlg():Boolean { return _attackKeyKeepFlg; }
/**
        * コンストラクタ
        */
public function ObjectKeyState()
{
_attackKey        = false;
_attackKeyKeepFlg = false;
}
/**
        * キー状態設定
        * 
        * @param keyState キー状況
        */
public function setKeyState(keyState:KeyState):void
{
// 押しっぱなし状態判定
if (_attackKey && keyState.attackKey)
{
_attackKeyKeepFlg = true;
}
else
{
_attackKeyKeepFlg = false;
}
// キー状態設定
_attackKey = keyState.attackKey;
}
}
}

例えば攻撃キーを押した場合攻撃するという処理をする場合

private var _state:ObjectKeyState;
private function exec():void
{
if (_state.attackKey && !_state.attackKeyKeepFlg)
{
// 攻撃処理
}
}

とすることで、攻撃キー押しっぱなしの場合攻撃処理が実行されないようにできます。


あとがき

これでいちいちイベントイベントさせなくても、

とりあえず全部ENTER_FRAMEの処理内で解決できそうですね!