LoginSignup
0
0

More than 3 years have passed since last update.

【DXライブラリ】キーボードの入力状態を調べる【ちょい改】

Last updated at Posted at 2021-02-23

こんにちは

以前キーボードの入力状態を調べるという記事でキー入力をC++/DXライブラリでクラス化する記事を書きました。

そして先日のアドベントカレンダー記事のdxlib 小技集(役に立つかは保証できません)(@takuro7021)内で、次のような言及がありました。

けどここの方法だと使うキーが増えるたびにオブジェクトを作る必要があります。しかもよく読んでみるとわかるんですけど、キーの数だけupdateを実行する必要がありますし、僕の勘違いでなければGetHitKeyStateAllは本来1フレーム(ゲームのメインループ一回)に一回呼べばいいのにこれじゃキーの数だけ呼ばれてしまいます。

およ?と思い改めて自分のコードを読み直しました。

virtual void Update() {
        char isKey[256]; // 現在のキーの入力状態を格納する
        int tmpKey;
        if (GetHitKeyStateAll(isKey) == -1) {
            //System::MessageError(ERR_INPUT_KEY);
        }// 全てのキーの入力状態を得る
        tmpKey = mPressingCount;
        if (isKey[mCode] != 0) { // i番のキーコードに対応するキーが押されていたら
            mPressingCount++;     // 加算
            KeyStatus = mPressingCount > 1 ? DeviceStatus::Press : DeviceStatus::Down;
        }
        else {              // 押されていなければ
            if (tmpKey > 0) { //1フレーム前まで押されていたら
                KeyStatus = DeviceStatus::Up;
            }
            else {
                KeyStatus = DeviceStatus::Release;
            }
            mPressingCount = 0;   // 0にする
        }
    }

これですね

元記事読んでもらえるとわかると思いますが、キー一つ一つのオブジェクトがこのUpdate関数を持ち、毎フレーム更新しています。つまり、GetHitKeyStateAll(isKey)は1フレームにつき100回以上呼び出されています。じっさいこの関数は1フレーム一回呼べばいいはずなのです。(そういう指摘コメントは記事のほうに書いてくれてもいいのよ!)

個人的なこと

個人的に思ったことを書いているだけですので読む必要はありません。

記事のちょっとしたのほうに別方法が記載された参考リンクがあります。こちらの方法もいいと思います。ですが私はいまC#メインとなり、KEY_INPUT_Aのような定数もDX.KEY_INPUT_Aと変わりDX.をいちいち打つのもめんどい。というかC#なんだからクラス化したい。というかこれだと自分が必要な情報がすべて集まらないんですよね。
また、Siv3DというC++ライブラリがあるのですが、こちらはなかなかきれいにクラスにまとまっていてかんたんなコードで書けるというメリットもあり気に入っています。でもDXライブラリのほうが自分でやっている感じがして楽しい。となるとDXライブラリでSiv3Dのようなコードに似せればよい。となりました。

以上を踏まえてこの前のをそのままC#に流用するとともに改良を加えることにしました。

本題

構造は単純で、引数で渡せば済む話です。いまC#メインに切り替えたのでC++のコードはないのですが、少し変えれば動くはずです。

void Update(byte[] key)
{
     // 現在のキーの入力状態を格納する
    var tmpKey = Count;

    if (key[Code] != 0)
    { // i番のキーコードに対応するキーが押されていたら
        Count++;     // 加算
        State = Count > 1 ? DeviceState.Press : DeviceState.Down;
    }
    else
    {// 押されていなければ
        if (tmpKey > 0)
        { //1フレーム前まで押されていたら
            State = DeviceState.Up;
        }
        else
        {
            State = DeviceState.Release;
        }
        Count = 0;   // 0にする
    }
}

少し変数名等は変わっていますが基本同じ。メインループの頭らへんで

byte[] isKey = new byte[256];
if (DX.GetHitKeyStateAll(isKey) != -1)
{
    Key1.Update(isKey);
    Key2.Update(isKey);
//---------略------------
}

とでも呼べば、GetHitKeyStateAll関数呼び出しは1フレーム1回で済みました。
これで現状自分が認知している課題は解決しました。マウスも同じようにやっています。

何かあったらコメントへ

(記事適当でごめんなさい...)

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0