ホームへ戻る

 2.9章 全てのキーの入力状態を取得する

 DXライブラリは完璧なまでに便利な関数が揃っているのですが、一つだけ自分で実装しなければならない関数があります

DXライブラリの関数に「キーが押されれいるか」を取得する関数はありますが「どれ位キーが押されているか」を取得する関数はありません。

選択項目を移動する場合など、「下キーが押されたら選択項目を一つ下に移動」のような処理をさせたいことがあります。



このようなメニュー画面で下キーを押した時は一つだけ選択項目が移動して欲しいですね。

しかし

while(1){
  if( 下キーが押されている ){
    選択項目を下に一つずらす;
  }
}

このような処理をするとどうなるでしょう。while文は1秒間に60回まわっていますから、1秒間下キーを押しっぱなしにすると、60回下に選択項目が移動します。

すぐにキーを離したとしてもいくつか選択項目が進んでしまうことでしょう。

一度このことをサンプルプログラムで確認してみましょう。


#include "DxLib.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

        int x=0;

        // while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

                DrawFormatString( x, 0, GetColor(255,255,255), "?!" );

                if( CheckHitKey(KEY_INPUT_RIGHT) != 0 ){
                        x = x + 50;
                }

        }

        DxLib_End(); // DXライブラリ終了処理
        return 0;
} 


右キーを押してみてください。押すたびに一つずつ移動するのではなく、ものすごい勢いで右に飛んで行ってしまうと思います。

キーが押されている時に処理をするのではなく、「押された瞬間」=(押されて1フレーム目)だけ処理をさせたいのですが、DXライブラリの標準関数だけではこれができません。

そこで、「どれ位キーが押されているか」を取得することが出来る関数を作ってみましょう。

まず、DXライブラリの全てのキーの入力状態を取得する関数は GetHitKeyStateAll関数 です。 GetHitKeyStateAll関数 のリファレンスを確認 してみましょう。

宣言 int GetHitKeyStateAll( char *KeyStateBuf ) ;

概略 キーボードのすべてのキーの押下状態を取得する

引数 char *KeyStateBuf : すべてのキーの押下状態を格納するバッファのポインタ

今までに CheckHitKey関数 を使う事で Escキー などの特定のキーの入力状態がチェックできることをお伝えしました。

しかし、沢山のキーの入力状態を確認したい時は、一つずつこの関数を呼んでいたので非効率です。そこで、全てまとめて取得できる GetHitKeyStateAll関数 を使用します。

引数に渡す変数はキーの入力状態(0か1)を入れるための char型配列 です。

キーは全部で256種類ありますから、必ず

char key[256];
GetHitKeyStateAll( key );

のように呼ばなければなりません。関数を呼ぶとキーコードごとに全てのキーの入力状態が key に格納されます。

どの番号がどのキーに対応しているかは、リファレンスに書いてありますが、こちらにも書いておきます。

キーコード 説明 キーコード 説明 キーコード 説明
KEY_INPUT_BACK // バックスペースキー KEY_INPUT_NUMPAD0 // テンキー0 KEY_INPUT_A // Aキー
KEY_INPUT_TAB // タブキー KEY_INPUT_NUMPAD1 // テンキー1 KEY_INPUT_B // Bキー
KEY_INPUT_RETURN // エンターキー KEY_INPUT_NUMPAD2 // テンキー2 KEY_INPUT_C // Cキー
KEY_INPUT_NUMPAD3 // テンキー3 KEY_INPUT_D // Dキー
KEY_INPUT_LSHIFT // 左シフトキー KEY_INPUT_NUMPAD4 // テンキー4 KEY_INPUT_E // Eキー
KEY_INPUT_RSHIFT // 右シフトキー KEY_INPUT_NUMPAD5 // テンキー5 KEY_INPUT_F // Fキー
KEY_INPUT_LCONTROL // 左コントロールキー KEY_INPUT_NUMPAD6 // テンキー6 KEY_INPUT_G // Gキー
KEY_INPUT_RCONTROL // 右コントロールキー KEY_INPUT_NUMPAD7 // テンキー7 KEY_INPUT_H // Hキー
KEY_INPUT_ESCAPE // エスケープキー KEY_INPUT_NUMPAD8 // テンキー8 KEY_INPUT_I // Iキー
KEY_INPUT_SPACE // スペースキー KEY_INPUT_NUMPAD9 // テンキー9 KEY_INPUT_J // Jキー
KEY_INPUT_PGUP // PageUPキー KEY_INPUT_MULTIPLY // テンキー*キー KEY_INPUT_K // Kキー
KEY_INPUT_PGDN // PageDownキー KEY_INPUT_ADD // テンキー+キー KEY_INPUT_L // Lキー
KEY_INPUT_END // エンドキー KEY_INPUT_SUBTRACT // テンキー-キー KEY_INPUT_M // Mキー
KEY_INPUT_HOME // ホームキー KEY_INPUT_DECIMAL // テンキー.キー KEY_INPUT_N // Nキー
KEY_INPUT_LEFT // 左キー KEY_INPUT_DIVIDE // テンキー/キー KEY_INPUT_O // Oキー
KEY_INPUT_UP // 上キー KEY_INPUT_NUMPADENTER // テンキーのエンターキー KEY_INPUT_P // Pキー
KEY_INPUT_RIGHT // 右キー KEY_INPUT_Q // Qキー
KEY_INPUT_DOWN // 下キー KEY_INPUT_F1 // F1キー KEY_INPUT_R // Rキー
KEY_INPUT_INSERT // インサートキー KEY_INPUT_F2 // F2キー KEY_INPUT_S // Sキー
KEY_INPUT_DELETE // デリートキー KEY_INPUT_F3 // F3キー KEY_INPUT_T // Tキー
KEY_INPUT_F4 // F4キー KEY_INPUT_U // Uキー
KEY_INPUT_MINUS // -キー KEY_INPUT_F5 // F5キー KEY_INPUT_V // Vキー
KEY_INPUT_YEN // ¥キー KEY_INPUT_F6 // F6キー KEY_INPUT_W // Wキー
KEY_INPUT_PREVTRACK // ^キー KEY_INPUT_F7 // F7キー KEY_INPUT_X // Xキー
KEY_INPUT_PERIOD // .キー KEY_INPUT_F8 // F8キー KEY_INPUT_Y // Yキー
KEY_INPUT_SLASH // /キー KEY_INPUT_F9 // F9キー KEY_INPUT_Z // Zキー
KEY_INPUT_LALT // 左ALTキー KEY_INPUT_F10 // F10キー KEY_INPUT_0 // 0キー
KEY_INPUT_RALT // 右ALTキー KEY_INPUT_F11 // F11キー KEY_INPUT_1 // 1キー
KEY_INPUT_SCROLL // ScrollLockキー KEY_INPUT_F12 // F12キー KEY_INPUT_2 // 2キー
KEY_INPUT_SEMICOLON // ;キー KEY_INPUT_3 // 3キー
KEY_INPUT_COLON // :キー KEY_INPUT_4 // 4キー
KEY_INPUT_LBRACKET // [キー KEY_INPUT_5 // 5キー
KEY_INPUT_RBRACKET // ]キー KEY_INPUT_6 // 6キー
KEY_INPUT_AT // @キー KEY_INPUT_7 // 7キー
KEY_INPUT_BACKSLASH // \キー KEY_INPUT_8 // 8キー
KEY_INPUT_COMMA // ,キー KEY_INPUT_9 // 9キー
KEY_INPUT_CAPSLOCK // CaspLockキー
KEY_INPUT_PAUSE // PauseBreakキー


例えば Zキー が押されているかどうかは

if( key[ KEY_INPUT_Z ] != 0 ){
}

で分かるわけです。

さて、これを使って「何フレーム押されているか」を計算する関数「gpUpdateKey関数」を作ります

※ 本サイトで独自に作成した関数名には先頭に「gp」(game programingの略)を付けることにします。

まず、グローバル変数で

int Key[256];

を宣言しておき、メイン関数で gpUpdateKey関数 が呼ばれるたびに

全てのキーの入力状態を見て、押されているキーコードのキーフレーム数を加算します。


#include "DxLib.h"

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

        int x=0;

        // while(裏画面を表画面に反映, メッセージ処理, 画面クリア, キーの状態更新)
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){

                DrawFormatString( x, 0, GetColor(255,255,255), "?!" ); // x,0 の位置に白で ?! を描画

                if( Key[KEY_INPUT_RIGHT] == 1 ){ // 右キーが押された瞬間なら
                        x = x + 50;                 // xを50加算
                }

        }

        DxLib_End(); // DXライブラリ終了処理
        return 0;
} 

実行結果


        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
このように書くことで、256種類あるキー全ての入力状態を見て、入力されているキーコードに対応するキーの入力フレーム数を加算出来ます。

つまり、Key[ キーコード ]に入っている数値が押されているフレーム数であり、これが1の時のみ処理をすれば、押された瞬間処理をすることが出来るのです。

また、押されているフレーム数が分かるので「押しっぱなし判定」も可能です。

下に、1秒以上Zキーを押しっぱなしなら、文字を表示するサンプルプログラムを用意しました。



#include "DxLib.h"

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

        // while(裏画面を表画面に反映, メッセージ処理, 画面クリア, キー更新)
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){

                if( Key[KEY_INPUT_Z] >= 60 ){ // 60フレーム以上押されていたら
	                DrawFormatString( 0, 0, GetColor(255,255,255), "?!" ); // 文字を表示
	        }

	}

	DxLib_End(); // DXライブラリ終了処理
	return 0;
} 


60FPSで動いている環境であれば、1秒押し続けることで、Key[KEY_INPUT_Z]のカウント数は1秒で60まで加算されますから、

これ以上の時に処理をすることで押しっぱなし時の処理が可能になります。

→分からないことがあれば掲示板で質問して下さい


- Remical Soft -