ページ 11

キーボードの入力

Posted: 2012年11月25日(日) 19:42
by dic
初歩的なことでつまづきました
今、キーボード入力で、押しっぱなしはそのまま数値を+1していって増やし
キーボード入力がなかったら ゼロにもどす という方法で押しっぱなしを防ごうかと考えています
そこで、下のソースを作ったのですが、妙な動作をするのでどこかにおかしいところがないかみてもらいたいです

void CSub::KeybordInput() 関数は毎フレーム呼び出されます
起動すると、最初の状態は zeo を表示し、F10を押すと zero が表示されず 2回目のF10を押すと zero が表示されます
何回か試したところ 奇数回数のF10は zero が表示されず、偶数では zero が表示されます
どこか、おかしいところはないでしょうか?よろしくおねがいします。

コード:

//==================================================================
// グローバル変数
EXTN int g_Key[1024];
...
...
...
void	CSub::KeybordInput()
{
	char	key[1024];
	memset( key, 0, sizeof(key) );
	GetHitKeyStateAll( key );

	//	キーボード -> ジョイスティク
	if( key[ KEY_INPUT_UP ] == 1 )
		g_Joystick1[ PAD_INPUT_UP ]++;
	if( key[ KEY_INPUT_DOWN ] == 1 )
		g_Joystick1[ PAD_INPUT_DOWN ]++;
	if( key[ KEY_INPUT_LEFT ] == 1 )
		g_Joystick1[ PAD_INPUT_LEFT ]++;
	if( key[ KEY_INPUT_RIGHT ] == 1 )
		g_Joystick1[ PAD_INPUT_RIGHT ]++;

	if( key[ KEY_INPUT_A ] )
		g_Joystick1[ PAD_INPUT_A ]++;
	if( key[ KEY_INPUT_B ] )
		g_Joystick1[ PAD_INPUT_B ]++;
	if( key[ KEY_INPUT_C ] )
		g_Joystick1[ PAD_INPUT_C ]++;
	if( key[ KEY_INPUT_X ] )
		g_Joystick1[ PAD_INPUT_X ]++;
	if( key[ KEY_INPUT_Y ] )
		g_Joystick1[ PAD_INPUT_Y ]++;
	if( key[ KEY_INPUT_Z ] )
		g_Joystick1[ PAD_INPUT_Z ]++;

	//	キーボードの入力
	int	i;
	int	push = 0;
	for( i=0; i<1024; i++ )
	{
		if( key[i] )
		{
			//	入力があった
			push = 1;
		}
	}

	//	入力があった
	if( push == 1 )
	{
		if( key[KEY_INPUT_F10] )
			g_Key[KEY_INPUT_F10]++;
	}
	//	入力がなかった
	if( push == 0 )
	{
		memset( g_Key, 0, sizeof(g_Key) );
		DrawString( 120, 120, "zero", GetColor(255,255,0) );
	}

}

Re: キーボードの入力

Posted: 2012年11月25日(日) 21:44
by dic
http://homepage2.nifty.com/natupaji/DxL ... html#R5N28
にあるGetHitKeyStateAll関数の説明にあった下の文章

使うにはまず char 型変数 256 個の配列を宣言します。必ず char 型で、数は 256 個でないといけません。

とあったので、int key[1024]; を char key[256]; にして変更し、またF10ではなく F11にしたところうまくいきました

解決したソースコードをデバック用コードも含めて以下に貼っておきます

コード:

//==================================================================
EXTN int g_Key[256];
...
...
...
void	CSub::KeybordInput()
{
	char	key[256];
	memset( key, 0, sizeof(key) );
	GetHitKeyStateAll( key );

	//	キーボード -> ジョイスティク
	if( key[ KEY_INPUT_UP ] == 1 )
		g_Joystick1[ PAD_INPUT_UP ]++;
	if( key[ KEY_INPUT_DOWN ] == 1 )
		g_Joystick1[ PAD_INPUT_DOWN ]++;
	if( key[ KEY_INPUT_LEFT ] == 1 )
		g_Joystick1[ PAD_INPUT_LEFT ]++;
	if( key[ KEY_INPUT_RIGHT ] == 1 )
		g_Joystick1[ PAD_INPUT_RIGHT ]++;

	if( key[ KEY_INPUT_A ] )
		g_Joystick1[ PAD_INPUT_A ]++;
	if( key[ KEY_INPUT_B ] )
		g_Joystick1[ PAD_INPUT_B ]++;
	if( key[ KEY_INPUT_C ] )
		g_Joystick1[ PAD_INPUT_C ]++;
	if( key[ KEY_INPUT_X ] )
		g_Joystick1[ PAD_INPUT_X ]++;
	if( key[ KEY_INPUT_Y ] )
		g_Joystick1[ PAD_INPUT_Y ]++;
	if( key[ KEY_INPUT_Z ] )
		g_Joystick1[ PAD_INPUT_Z ]++;

	//	キーボードの入力
	int	i;
	int	push;
	int	y = 0;
	push = 0;
	for( i=0; i<256; i++ )
	{
		if( key[i] )
		{
			//	入力があった
			push = 1;
			DrawFormatString( 120, 200+y*20, GetColor(255,255,0), "%d", i );
			y++;
		}
	}

	//	入力があった
	if( push == 1 )
	{
		if( key[KEY_INPUT_F11] )
			g_Key[KEY_INPUT_F11]++;
		DrawString( 120, 120, "input", GetColor(255,255,0) );
	}
	//	入力がなかった
	if( push == 0 )
	{
		memset( g_Key, 0, sizeof(g_Key) );
		DrawString( 120, 120, "zero", GetColor(255,255,0) );
	}

}

Re: キーボードの入力

Posted: 2012年11月26日(月) 00:20
by ガラくた屋
間違ってたらすみません
なんとなくですが
キーボード入力限定ならkbhit()とgetch()で入力判断ではだめなのでしょうか?
kbhit()は入力されたら
そのしたにgetch()で入力を受け取ればあとは同じかどうかフラグを立てて判断すればよい気がします

Re: キーボードの入力

Posted: 2012年11月26日(月) 08:30
by dic
>>ガラくた屋さん
_getch() ですか 知りませんでしたので MSDNで調べると

解説

_getch 関数はコンソールからエコーなしで 1 文字読み込みます。_getche 関数はコンソールから 1 文字読み込み、読み込んだ文字をエコーします。

とあり、コンソール用ではないかと思います

今回はWindowsアプリなので、コンソール用は動くのか?一応下のソースで試してみましたがー1しか返ってきませんでした
あと、処理速度的なことで、DirectInput系ではないので多少不安はあります

コード:

	int	ch;
	ch = _getch();
	DrawFormatString( 120, 140, GetColor(255,255,0), "ch:%d", ch );
なにはともあれ Windowsアプリでは _getch() はうまく動かないみたいでした

Re: キーボードの入力

Posted: 2012年11月26日(月) 10:41
by beatle
push変数について、意図していることならいいのですが心配なので書きます。

push変数は初期値0で定義された後、いずれかのキーが押されていれば1が代入され、1つのキーが押されていなければ0のままです。
したがって、F11キーに限らず、AとかENTERとか、何かキーが押されていたらpush == 1は成り立ちます。

要するに

コード:

    if( push == 1 )
    {
        if( key[KEY_INPUT_F11] )
            g_Key[KEY_INPUT_F11]++;
        DrawString( 120, 120, "input", GetColor(255,255,0) );
    }
この6行の意図していることがいまいち分かりませんでした。

Re: キーボードの入力

Posted: 2012年11月26日(月) 15:24
by dic
これ以上シンプルに設計するのは私には無理ですが、
どのような想定なのかというと、毎フレーム呼び出され キーボードの入力(どのキーでもいい)があれば
push = 1; として、入力があったとします
そして次の if ( push == 1 ) の中でどのキーの入力があったかを調べています
今のソースではF11キーのみ検出しています
そして、グローバル変数 int g_Key[256]; の g_Key[KEY_INPUT_F11] の変数をインクリメント
次のフレームでもF11の入力があれば g_Key[KEY_INPUT_F11] = 2; となります

まったく入力がないと push = 0; となり次のif文 if( push == 0 ) をとおり
g_Key の内容はゼロになります

これによって、任意のキー(ここではF11)の押しっぱなしを検出し、g_Key[KEY_INPUT_F11] = 1 のときが1フレーム目の
キー入力、g_Key[KEY_INPUT_F11] = 2; のときは2フレーム目の入力、これは押しっぱなしという判定
キー入力がないと g_Key は配列すべてゼロ これは何も押していない状態と判定しています

A とか ENTER に対応したいときは

コード:

if( push == 1 )
{
  if( key[KEY_INPUT_F11] )
    g_Key[KEY_INPUT_F11]++;
  if( key[KEY_INPUT_A] )
    g_Key[KEY_INPUT_A]++;
  if( key[KEY_INPUT_ENTER] )
    g_Key[KEY_INPUT_ENTER]++;
}
と追加すれば問題ないと思っています

2段階にわけて、入力を判定しています

と、これ以上説明しようがないです

Re: キーボードの入力

Posted: 2012年11月26日(月) 16:06
by beatle
僕だったらこんな感じにする、というのを書いておきますね。
参考になれば幸いです。
(zero, inputと表示する機能は削りました。どうせデバッグ用ですよね?)

コード:

void    CSub::KeybordInput()
{
    char    key[256];
    GetHitKeyStateAll( key );
 
    //  キーボード -> ジョイスティク
    if( key[ KEY_INPUT_UP ] == 1 )
        g_Joystick1[ PAD_INPUT_UP ]++;
    ...
 
    //  キーボードの入力
    int i;
    int y = 0;
    for( i=0; i<256; i++ )
    {
        if( key[i] )
        {
            //  入力があった
            g_Key[i]++;
            DrawFormatString( 120, 200+y*20, GetColor(255,255,0), "%d", i );
            y++;
        }
        else
        {
            g_Key[i] = 0;
        }
    }
}
それから、ifを何個も書き連ねる場合、else ifを使うほうが効率の面では良いです。

コード:

  if( key[KEY_INPUT_F11] )
    g_Key[KEY_INPUT_F11]++;
  else if( key[KEY_INPUT_A] )
    g_Key[KEY_INPUT_A]++;
  else if( key[KEY_INPUT_ENTER] )
    g_Key[KEY_INPUT_ENTER]++;

Re: キーボードの入力

Posted: 2012年11月26日(月) 17:43
by ISLe
やりたいことは龍神録プログラミングの館のGetHitKeyStateAll_2関数と同じことではないのですかね。

F11を離してもその間に他のキーを押していればカウントが継続される仕様になっているので、キー入力が無くなったらゼロに戻すとおっしゃったのが、キー入力が『一切』無くなったらという意味であれば合ってますけどね。


>beatleさん
else入れると同時入力で後ろがカウントしなくなります。

Re: キーボードの入力

Posted: 2012年11月26日(月) 17:51
by dic
なるほど、たしかにインデックスが同じ値ですね
気づきませんでした

同じインデックス値ということで、上にある キーボードー>ジョイスティック のところも
改良できそうです

参考になりました

Re: キーボードの入力

Posted: 2012年11月26日(月) 19:38
by ガラくた屋
ハッカーさんすみません
getch関数がwindowsで使えないの言われて思い出しました。
すいませんでした

Re: キーボードの入力

Posted: 2012年11月27日(火) 07:01
by dic
>>ISLeさん
今調べましたところGetHitKeyStateAll_2関数と同じことをやってますね

>>ガラくた屋さん
こちらこそ、仕様を読んでなくてミスすることは結構あります
落ち着いてプログラム入力したいものです