選択肢について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
悪戦苦闘している大学生

選択肢について

#1

投稿記事 by 悪戦苦闘している大学生 » 18年前

初めまして.
私は現在大学生で,卒業制作にDXライブラリでゲーム製作しようと意気込んでいるのですが,
早速壁にぶち当たりましたので,質問させていただきました.

まず,環境その他を説明させていただきます.
OSはWindowXP,開発環境はVisualStudio2005です.
開発言語はC++で,私を含めまして,総勢3名での開発を目指してします.
参考資料としまして,DXライブラリを開発された方が著された,
「14歳からはじめるC++ わくわくゲームプログラミング」を用いております.
また,貴サイト「C言語~ゲームプログラミングの館~」は,
DXライブラリの基礎の部分で非常にお世話になっております.
ありがとうございます.


現在,タイトルの通り,選択肢を実装するところで躓いております.
と言いますのも,貴サイトにて解説されていました,
「33. 選択画面の作り方。」を参考に,選択画面の処理を実装してみました.
具体的には,例えば「START」と「EXIT」のような選択肢があるとしますと,
それぞれ画像を2枚準備し,選択状態にあるかないかで画像を切り替えるというものです.
なお,この処理はクラスのメンバ関数内で定義しており,
オブジェクトが持つゲームの状態(TITLE画面なのかMAIN画面なのか)をwhileループ内のswitch文で判定し,
当該メンバ関数を呼び出しています.
(参考資料の第4章,GameFrameクラスに相当)


まず,解説されている内容を参考にして,選択が上にも動くように実装しました.
躓いているのは,選択が動くスピードが異常といいますか,とにかく早いのです.


解説されているソースを丸々コピーしてコンパイルすると,
選択状態を表す「■」は正常な速度で動きます.(当たり前ですが…)
そこで,選択処理の部分をコピーし,メンバ関数にはりつけたのですが,
やはり処理が異常に早く,一回↓キーを押しただけで,ルーレット状態となってしまいます.

次に,whileループ内に,メンバ関数を呼び出すのではなく,当初の選択処理を直接記述すると,
選択は正常に動作しました.
念のため試してみたのですが,「■」を動作させる処理をメンバ関数内で処理すると,
やはりルーレット状態になってしまいました.


以上の点から,メンバ関数に記述していること自体が問題だと思うのですが,
一応,処理の流れ上,ループする毎にScreenFlip();関数が呼び出されているはずなので,
何故このような状態に陥るのか分からず,解決できないでおります.
なお,STARTが選択されている状態で「z」キーを押すと,
ちゃんとメイン画面に切り替わるので,ループ処理にも問題はないと思います.


ソースの一部を,別にレスして載せますので,どなたかご助言いただけませんでしょうか.
よろしくお願いいたします.

悪戦苦闘している大学生

Re:選択肢について

#2

投稿記事 by 悪戦苦闘している大学生 » 18年前

whileループ
while(!(bool)ProcessMessage() && !(bool)ClearDrawScreen() && !(bool)CheckHitKey(KEY_INPUT_ESCAPE)){
	switch(test.gstate){
		case GAME_TITLE:
			test.drawGameTitle();
			break;
		case GAME_MAIN:
			DrawString(100, 100, "testText(MAIN)", GetColor(255, 255, 255));
			break;
		case GAME_EXIT:
			DxLib_End();
			return EXIT_SUCCESS;

	}

	ScreenFlip();
}



drawGameTitle()メンバ関数(テスト用にコピーしたので,コメント等がそのままになっています.)
ソース引用→http://dixq.net/g/#33
void GameFrame::drawGameTitle()
{
        int DownOshita=0,NewDown=0,OldDown=0,DownPusingCounter=0;//各種フラグの宣言

        char_disp(GetColor(255, 255, 255),y);            

        if( KeyBuf[ KEY_INPUT_DOWN ] == 1 )  
                NewDown=1;                                  // 今押されている状態に
        else                                             // 押されていなかったら
                NewDown=0;                                  // 今押されていない状態に
                                
        if( OldDown==0 && NewDown==1 )                   // 前回押されてなく、今回押されていたら
                DownOshita=1;                               // たった今押された状態に
        else                                             // それ以外なら
                DownOshita=0;                               // たったいま押されていない状態に
                                
        if( OldDown==1 && NewDown==1 )                   // 前回も押され、今回も押されていたら
                DownPusingCounter++;                        // 押しっぱなしカウンターを増加
        else
                DownPusingCounter=0;

        if( DownOshita==1 || DownPusingCounter>30){ // たった今押したか、30カウンター以上押しっぱなしなら
                if(DownPusingCounter>30)              // 30カウンター以上押しっぱなしならカウンターを27へ
                        DownPusingCounter=27;         // オートの場合4回に1回下に下がる。
                y+=20;                                           
                if(y==260)                            // y座標が260なら(選択が一番下なら)
                        y=100;                        // 選択座標を一番上に
        }
        OldDown=NewDown;                              // 新しい入力情報を古い入力情報へ
}



質問文に記しましたように,こういった記述だと,
↓キーを押すとルーレットのように早く回ります.(1回押しただけで,4,5つ下に行ってしまいます.)

一応,WaitTimer()関数を挟むことで,無理やり反応を鈍らせることはできるのですが,
あまりにも挙動不審なので,できれば正常な状態で選択画面を実装したいと考えております.


長文,大変失礼いたしました.
よろしくお願いいたします.

バグ

Re:選択肢について

#3

投稿記事 by バグ » 18年前

押しっ放しの場合に移動しないようにしてはどうでしょうか?

1:下キーが押されていて、フラグ用変数が0以外の場合に2へ進む

2:カーソル移動処理をして、フラグ用変数を0以外にする

3:下キーが押されていなければフラグ用変数を0にする。

というような処理を行なえば、下キーが押された初回の1回だけ移動すると思いますよ(^-^)

悪戦苦闘している大学生

Re:選択肢について

#4

投稿記事 by 悪戦苦闘している大学生 » 18年前

>バグ様
ご助言,ありがとうございます.
自分なりにそれを実現してみようとしたのですが,何故か今度は動かなくなってしまいました.



今日一日,改めてソースと睨めっこしていたら,やっと原因が分かりました.
・上に載せたソースがルーレット状態に陥ってしまう原因と思われるもの
→メンバ関数内で,DownOshitaなどの各種フラグ変数を初期化してしまっていたこと.

恐らく,これが一番の原因だと思います.
これを別のところで宣言したところ,正常に機能しました.

また,これを受けて,コメントとして残していた当初記述していたソースを見直してみると,
OldDown=NewDown;に相当する記述がぽっかり抜けてしまっていたようで…


初歩的なミスに全然気づかず,また思いこみが原因だったにも関わらず,
勇み足で質問してしまいまして,申し訳ございませんでした.


ご回答くださいましたバグ様をはじめ,皆様には大変ご迷惑をおかけいたしました.
また,何か問題が発生しましたら質問させていただくこともあるかと思いますが,
そのときはしっかりと全ての可能性を検証した上で,質問させていただきます.

ありがとうございました.

閉鎖

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