ページ 11

龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 12:15
by dast
こんにちは。何度もお世話になっています。
龍神録の8章のkey.cppの

コード:

//パッドとキーボードの両方の入力をチェックする関数
void GetHitPadStateAll(){
        int i,PadInput,mul=1;
        PadInput = GetJoypadInputState( DX_INPUT_PAD1 );//パッドの入力状態を取得
        for(i=0;i<16;i++){
                if(PadInput & mul)  pad.key[i]++;
                else                pad.key[i]=0;
                mul*=2;
        }
        input_pad_or_key(&pad.key[configpad.left]   ,CheckStateKey(KEY_INPUT_LEFT    ));
        input_pad_or_key(&pad.key[configpad.up]     ,CheckStateKey(KEY_INPUT_UP      ));
        input_pad_or_key(&pad.key[configpad.right]  ,CheckStateKey(KEY_INPUT_RIGHT   ));
        input_pad_or_key(&pad.key[configpad.down]   ,CheckStateKey(KEY_INPUT_DOWN    ));
        input_pad_or_key(&pad.key[configpad.shot]   ,CheckStateKey(KEY_INPUT_Z       ));
        input_pad_or_key(&pad.key[configpad.bom]    ,CheckStateKey(KEY_INPUT_X       ));
        input_pad_or_key(&pad.key[configpad.slow]   ,CheckStateKey(KEY_INPUT_LSHIFT  ));
        input_pad_or_key(&pad.key[configpad.start]  ,CheckStateKey(KEY_INPUT_ESCAPE  ));
        input_pad_or_key(&pad.key[configpad.change] ,CheckStateKey(KEY_INPUT_LCONTROL));
}



コード:

        for(i=0;i<16;i++){
                if(PadInput & mul)  pad.key[i]++;
                else                pad.key[i]=0;
                mul*=2;
        }
の部分ですが、これは一体何をしているのでしょうか?
なんとなくキーの数だけ処理をしてキーの入力状態を監視しているということはわかるのですが、具体的にどんな条件で分岐してどんな処理でキーの入力を判断しているのかが分かりません。
演算子の&をググっても「ビット積」なるよく分からない計算が出てきた上に、それがこの記述にどうやって関わっているのかが良く分かりません。
初歩的っぽい質問な上にここはそのまま覚える類の部分なのかもしれませんが気になったので質問しました。お手数かけてすみません。

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 12:44
by softya(ソフト屋)
論理演算(ビット演算子)は覚えたほうが良いでしょうね。
2進数や16進数は理解できますか?
「ビット演算子」
http://www.geocities.jp/ky_webid/c/049.html

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 13:08
by dast
リンク先のページを読ませていただきました。
要するに指定した数値を2進数に直して各桁で掛け算をするといった認識でよろしいでしょうか?

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 13:13
by softya(ソフト屋)
dast さんが書きました:リンク先のページを読ませていただきました。
要するに指定した数値を2進数に直して各桁で掛け算をするといった認識でよろしいでしょうか?
>2進数に直して
int型やchar型は内部的には2進数として保持されています。
つまり、10進数で扱うのは人が使いやすいからに過ぎません。

あと桁上がりはしませんので、ただの積とは違いますけどね。

それで、肝心のGetHitPadStateAllの意図は理解できたのでしょうか?

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 16:51
by dast
いいえ、恥ずかしながらビット積のことが分かってもこの場合どういう結果になったら分岐するのかが良く分かりません。if(PadInput & mul)となっているだけでどういう結果になったらpad.key++;を処理するようになるのかが書いていないように見えますし…

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 16:55
by softya(ソフト屋)
まず、if文で式の結果が0以外の値の場合は真とみなします。
あとは、GetJoypadInputStateで得られるPadInputがどんな値なのか調べてみてください。

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 17:06
by ISLe
条件式(PadInput & mul)で、mulの値がループの中でどのように変化していくか列挙してみてください。
最初は10進数で、そのあと2進数にしてみましょう。

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 19:49
by dast
まずはPadInputの値を調べようとhttp://dixq.net/forum/viewtopic.php?f=3&t=9264にあるプログラム(訂正後)のプログラムのmain.cppを次のように改造してみたらビルドできなくなりました。一体どうしたらビルドできるようになるでしょうか?

main.cpp

コード:

#define GLOBAL_INSTANCE
#include "../ヘッダー/GV.h"

		extern int PadInput;
//ループで必ず行う3大処理
int ProcessLoop(){
    if(ProcessMessage()!=0)return -1;//プロセス処理がエラーなら-1を返す
    if(ClearDrawScreen()!=0)return -1;//画面クリア処理がエラーなら-1を返す
    GetHitKeyStateAll_2();//現在のキー入力処理を行う
	GetHitPadStateAll();//現在のパッド入力処理を行う
    return 0;
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

    while(ProcessLoop()==0){//ProcessLoopの内容を行う
		switch(func_state){
			case 0://func_stateが0の時
				load();//function.hの関数load()を実行する
				first_ini();//function.hの関数first_ini()を実行する
				func_state = 100;//func_stateを100にする
				break;
			case 100:
				calc_ch();//function.hの関数calc_ch()を実行する
				graph_main();//function.hの関数graph_main()を実行する
		printfDx("%d\n",PadInput);
				break;
			default://上記のcase以外の場合
				printfDx("不明なfunc_state%d\n",func_state);
		printfDx("%d\n",PadInput);
				break;
		}

		if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break;//エスケープが入力されたらブレイク



        //ココ!!




        ScreenFlip();

    }

    DxLib_End();
    return 0;
}

ビルド文

1>------ ビルド開始: プロジェクト: 自作ゲーム, 構成: Debug Win32 ------
1>コンパイルしています...
1>main01.cpp
1>リンクしています...
1>main01.obj : error LNK2001: 外部シンボル ""int PadInput" (?PadInput@@3HA)" は未解決です。
1>C:\Users\PCUser\Documents\Visual Studio 2008\Projects\自作ゲーム - コピー\Debug\自作ゲーム.exe : fatal error LNK1120: 外部参照 1 が未解決です。
1>ビルドログは "file://c:\Users\PCUser\Documents\Visual Studio 2008\Projects\自作ゲーム - コピー\Debug\BuildLog.htm" に保存されました。
1>自作ゲーム - エラー 2、警告 0
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 19:52
by softya(ソフト屋)
ローカル変数は、関数内の寿命とスコープしか無いので参照できません。

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月14日(水) 22:51
by Dixq (管理人)
関数の振る舞いを調べたい時は大きなプロジェクトに組み込むのではなく、
http://homepage2.nifty.com/natupaji/DxL ... .html#R5N4
サンプルプログラムを実行する方が良いと思います。
DXライブラリのサンプルコードは非常に簡素なものなので、テストコード用のプロジェクトを一つ用意しておくと良いでしょう。

入力状態を取得し、それを2進数でリアルタイム表示してみて下さい。
そうすればどうなっているかすぐにわかるはずです。

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月16日(金) 17:02
by dast
次のようなプログラムを組んで(組んだというかサンプルプログラムに何文かぶっ刺しただけですけど)取得状態を表示するところまでは行ったんですけど前の文字が消えずに表示され続けて文字が重なってしまい見にくくなるという感じになってしまいます。この場合どうしたら前の文字を消すことができるでしょうか?

コード:

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
		 LPSTR lpCmdLine, int nCmdShow )

{    ChangeWindowMode(TRUE);//ウィンドウモード
	int Cr , PadInput ;

	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;	// エラーが起きたら直ちに終了
	}
	SetDrawScreen(DX_SCREEN_BACK);

	// 白色の値を取得
	Cr = GetColor( 255 , 255 , 255 ) ;
	ClearDrawScreen();

	// 文字列の描画
	DrawString( 150 , 240 - 32 , "パッドのSTARTボタンを押してください" , Cr );

	// パッド1の9ボタンの入力待ち
	PadInput = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
	
	while( ( PadInput & PAD_INPUT_9 ) == 0 )
	{printfDx("%d\n",PadInput);
		// メッセージ処理
		if( ProcessMessage() == -1 )
		{
			 break ;	// エラーが発生したらループを抜ける
             printfDx("%d\n",PadInput);
		}
		ScreenFlip();

		// パッド1の入力を取得
		PadInput = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
	}

	DxLib_End() ;		// DXライブラリ使用の終了処理

	return 0 ;		// ソフトの終了
}


Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月16日(金) 17:11
by softya(ソフト屋)

コード:

    while( ( PadInput & PAD_INPUT_9 ) == 0 )
    {printfDx("%d\n",PadInput); ← 値を%dだと確認しづらいと思います。16進数表示を調べてください。あと{の直後に書かないでください。

         ← 画面をクリアする関数が必要です。 この後で printfDxしてください、

        // メッセージ処理
        if( ProcessMessage() == -1 )
        {
             break ;    // エラーが発生したらループを抜ける
             printfDx("%d\n",PadInput); ← 同じ{}ブロック内のbreak;文の後の文は実行されません。
        }
        ScreenFlip();
 
        // パッド1の入力を取得
        PadInput = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
    }
ゲームプログラミングの基本構造の理解が足らないと思いますので、
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/
の内容を理解出来ていますでしょうか?龍神録よりも先にこちらだと思います。

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月17日(土) 01:42
by dast
わかりました。どうやら基礎の知識が足りていなかったようなので今あるトピックが解決したらそちらの方を先にやってみたいと思います。
お騒がせして申し訳ありませんでした。

Re: 龍神録8章に出てきたGetHitPadStateAll()の中身について

Posted: 2011年9月17日(土) 09:02
by softya(ソフト屋)
それとC言語の基礎知識も不足してますので、C言語のちゃんとした入門書を読まれることをお勧めします。