GetHitKeyStateAll()の仕組みがよくわかりません。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
らっせる
記事: 12
登録日時: 3年前

GetHitKeyStateAll()の仕組みがよくわかりません。

#1

投稿記事 by らっせる » 3年前

コード:

#include "DxLib.h"
int Key[256];
int gpUpdateKey(){
        char tmpKey[256];
        GetHitKeyStateAll( tmpKey );
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){
                        Key[i]++;
                } else {
                        Key[i] = 0;
                }
        }
        return 0;
}
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );
        int x=0;
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){
                DrawFormatString( x, 0, GetColor(255,255,255), "?!" );
                if( Key[KEY_INPUT_RIGHT] == 1 ){ //ここ!!
                        x = x + 50;
                }
        }
        DxLib_End();
        return 0;
} 
GetHitKeyStateAll()の仕組みがよくわかりません。
具体的にいうと
①tmpKey[0]には何が格納されているのでしょうか?右シフトキーの状態?バックスペースの状態?
②ソースコードの中にもコメント"//ここ!!"をいれたのですが、なぜ配列で0~256としているのに数字でもない"KEY_INPUT_RIGHT"が来るのでしょうか?

どなたかよろしく解説お願いします。

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 9年前
住所: 大阪府
連絡を取る:

Re: GetHitKeyStateAll()の仕組みがよくわかりません。

#2

投稿記事 by Hiragi(GKUTH) » 3年前

http://dxlib.o.oo7.jp/function/dxfunc_input.html#R5N28
リファレンスによると、要素数256のchar型配列へのポインタを渡すと各配列の要素にキーが押されていたら1、押されていなければ0が入っています。
tmpKeyにはGetHitKeyStateAllを呼んだ時点でのすべてのキーボードのキー状態が格納されています。
gpUpdateKey関数にて、すべての要素を探してtmpKeyに対応するKeyの要素に押されていれば値を増やす、つまり押されているフレーム数を代入しています。

KEY_INPUT_RIGHT などはDxLib.hの766行目から宣言されている定数ですので、配列の[]に定数を渡すとその定数の値が指し示す要素を参照し、その要素に
キーが押されているフレーム数が格納されているということです。
だいがくせい!

アバター
みけCAT
記事: 6246
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: GetHitKeyStateAll()の仕組みがよくわかりません。

#3

投稿記事 by みけCAT » 3年前

まず、DXライブラリの関数の話であると仮定します。
らっせる さんが書きました:①tmpKey[0]には何が格納されているのでしょうか?右シフトキーの状態?バックスペースの状態?
ここではDXライブラリ Ver3.16dのソースコードに基づいて解析します。

まず、GetHitKeyStateAll()関数はDxGateway.cppで定義され、NS_GetHitKeyStateAll()関数を呼び出しています。

NS_GetHitKeyStateAll()関数はDxInput.cppで定義され、
UpdateKeyboardInputState()関数で「キーボードの入力状態を更新」した後、「キーの入力値を変換」しています。
ここで使用されているInputSysDataはDxInput.hで定義されているINPUTSYSTEMDATA型で、KeyInputBufはunsigned char型の配列です。
従って、unsigned char型の精度が8ビットであればMSBがキーの状態として出力の配列に格納されます。

UpdateKeyboardInputState()関数もDxInput.cppで定義され、「環境依存処理」のUpdateKeyboardInputState_PF()関数を呼び出しています。

UpdateKeyboardInputState_PF()関数はWindows/DxInputWin.cppで定義され、
Windows APIのGetKeyboardState()関数を利用してキー情報を取得した後Windows/DxInputWin.cppで定義されたテーブルを用いて変換を行うか、
DirectInputのGetDeviceState()関数を利用してキー情報を取得しています。
GetKeyboardState()関数で取得できる情報は
「最上位ビットが 1 のときはキーが押されていることを、0 のときはキーが押されていないことを示します。」と定義されているので、
NS_GetHitKeyStateAll()関数での変換でキーが押されているかどうかを0/1で取得することができます。
また、DirectInputのGetDeviceState()関数で取得できる値は、キーボードの直接データにおいて
「IDirectInputDevice8::GetDeviceState メソッドの動作は、Microsoft Win32 の GetKeyboardState 関数と同じです。」
「このバイトの上位ビットが設定されている場合は、キーが押されています。」
と定義されています。
従って、同様にNS_GetHitKeyStateAll()関数での変換でキーが押されているかどうかを0/1で取得することができます。

ここで、テーブルで使用されるキーに対応する添字であるD_DIK_*はWindows/DxDirectX.hで定義されています。
この定義の中に0に定義されているものはありません。さらに、DirectInputを使用しない場合はキーの状態を全て0に初期化した後、
テーブルに格納された格納先の添字に対してデータの格納が行われます。
この格納先の添字は全てD_DIK_*が使われているので、0番目に代入が行われることはないので、0番目は常に0になります。
DirectInputを使用する場合は、GetKeyboardState()関数で取得した値で上書きされる右シフトを除いて、
DirectInputで取得した値が直接キー情報として格納されます。
これの0番目がどうなるかはわかりませんでしたが、DirectInput キー識別コード表で0番目の定義はなかったので、多分意味のない値だと思います。

まとめとして、GetHitKeyStateAll()が成功した場合、tmpKey[0]には
・DirectInputを使用しない場合、0
・DirectInputを使用する場合、意味のない値?
が格納されるでしょう。
らっせる さんが書きました:②ソースコードの中にもコメント"//ここ!!"をいれたのですが、なぜ配列で0~256としているのに数字でもない"KEY_INPUT_RIGHT"が来るのでしょうか?
数字を直接書く(マジックナンバー)よりDxLib.hで定義された定数を利用するほうがコードが読みやすく、エンバグしにくくなるからでしょう。
オフトピック
「配列で0~256としている」とはどういうことでしょうか?
ここで使用されている配列Keyは256要素であり、有効な要素はKey[0]~Key[255]です。
Key + 256はポインタ操作では有効ですが、デリファレンスしてはいけません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

らっ

Re: GetHitKeyStateAll()の仕組みがよくわかりません。

#4

投稿記事 by らっ » 3年前

みけCATさん、 Hiragi(GKUTH)さん解答ありがとうございます。
みけCATさんの回答に載っていたDirectInput キー識別コード表を確認しました。
試しに Key[KEY_INPUT_RIGHT]をKey[0x0E]と書き換えて実行したところバックスペースを押したときに?!が右にシフトし、
配列の要素数にはそれぞれ決まったキーの状態が0/1で格納されているという理解に達しました。
回答ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る