選択画面の作り方について

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

選択画面の作り方について

#1

投稿記事 by Eagle » 16年前

DXライブラリでゲーム作成をしています。

ゲームプログラミングの館
http://dixq.net/g/#33
の選択画面を作成中ゲームのスタート画面(と言うより最初の画面・・?)に使おうと思って
自分なりにコードを変えてみました。
#include "DxLib.h"
 
void char_disp(int White,int y){
        DrawString( 200 , y  , "⇒" , White );
        DrawString( 220 , 300 , "A" , White );
        DrawString( 220 , 320 , "B" , White );
        DrawString( 220 , 340 , "C" , White );
        DrawString( 220 , 360 , "D" , White );
        DrawString( 220 , 380 , "E" , White );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);        
    
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;

    int White , y=300;                                      //色とy座標の宣言
    White = GetColor( 255 , 255 , 255 ) ;                    //色の取得

    while(ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0){
        ClsDrawScreen();
        char_disp(White,y);                              // 文字を描画
        
	//移動
	int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);
        if( key & KEY_INPUT_DOWN==1 ||( key & KEY_INPUT_DOWN%5==0 && key & KEY_INPUT_DOWN>30)){
            y+=20;                                           
            if(y==400)
                y=300;
        }
 	if( key & KEY_INPUT_UP==1 ||( key & KEY_INPUT_UP%5==0 && key & KEY_INPUT_UP>30)){
            y-=20;                                           
            if(y==280)
                y=380;
        }
	//決定
	if( key & KEY_INPUT_Z ){
		if(y==380)	DxLib_End();	//終了
	}
        ScreenFlip();//裏画面反映
    }
    DxLib_End();
    return 0;
}
↑↓キーで矢印を動かして、Zキーが押されたら、矢印の座標に応じて動作を
するプログラムになると思ったのですが、
実行して見たところ、上下の移動がおかしく(?)なりました。。
どこがおかしいのか、考えましたがよくわかりません。
どの部分の書き方がおかしいのか教えてください。。。

Justy

Re:選択画面の作り方について

#2

投稿記事 by Justy » 16年前


>どこがおかしいのか、考えましたがよくわかりません。

  GetJoypadInputState() の戻り値に対して KEY_INPUT_UP とか [color=sans-serif]KEY_INPUT_Z[/font] を使って
判定することは正当なのか。

 リファレンスやサンプルなどを見て調べてみて下さい。

Libra

Re:選択画面の作り方について

#3

投稿記事 by Libra » 16年前

>KEY_INPUT_DOWN%5==0 && key & KEY_INPUT_DOWN>30

KEY_INPUT_DOWNやKEY_INPUT_UPは押されている時間を計測するものではないので、このような使い方は出来ないです。別途キーが押された時間を計算する変数を用意する必要があります。

追記:添付ソース
key & PAD_INPUT_Z⇒ key & PAD_INPUT_A が正しいです。

Eagle

Re:選択画面の作り方について

#4

投稿記事 by Eagle » 16年前

Justyさんの言っていた、
 GetJoypadInputState() の戻り値に対して KEY_INPUT_UP とか KEY_INPUT_Z を使って
 判定することは正当なのか。
を考えて見ます。

それを踏まえて、Libraさんの添付ファイルを参考にしながら、
自分なりにプログラムを書いてみます。

Justyさん、Libraさん
ありがとうございました。

nayo

Re:選択画面の作り方について

#5

投稿記事 by nayo » 16年前

#define BUTTON_NUM (6)

void get_input( int input[/url] );
void draw_menu( int select );

enum { P_UP, P_DOWN, P_LEFT, P_RIGHT, P_A, P_B };	// 使用するパッドのボタン
enum { M_START, M_OPTION, M_QUIT };			// メニュー
enum { G_MENU, G_OPTION, G_INIT, G_RUN };		// ゲームの状態

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
 
	// 初期化
	ChangeWindowMode(TRUE);        
	if( DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK ) != 0 ) return -1;

	// 変数宣言
	int select = 0, input[BUTTON_NUM], func_state = G_MENU;
	bool f_continue = TRUE;

	// メインループ
	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 && f_continue )
	{
		switch( func_state )
		{
		case G_MENU:
			get_input( input );	// 入力を得る
			// 上を押したら
			if( input[P_UP] == 1 || ( input[P_UP]>30 && input[P_UP]%5==0 ) ){
				select--;
				if( select < 0 ) select = 2;
			}
			// 下を押したら
			else if( input[P_DOWN] == 1 || ( input[P_DOWN]>30 && input[P_DOWN]%5==0 ) ){
				select++;
				if( select > 2 ) select = 0;
			}
			// 決定ボタンを押したら
			else if( input[P_A] == 1 ){
				switch( select )
				{
				case M_START: func_state = G_INIT;	break;
				case M_OPTION:func_state = G_OPTION;	break;
				case M_QUIT: f_continue = FALSE;	break;
				}
				select = 0;
			}
			draw_menu( select );	// メニュー描画
			break;
		case G_OPTION:
			// オプションの処理
			break;
		case G_INIT:
			// 初期化
			func_state = G_RUN;
			break;
		case G_RUN:
			// ゲーム処理
			break;
		}
		// FPSを60に設定するなど共通処理
		ScreenFlip();
	}

	// 終了処理
	DxLib_End();
	return 0;
}

// パッドの各ボタン入力を連続で押したカウントに直す関数
void get_input( int input[/url] )
{
	int pad = GetJoypadInputState( DX_INPUT_KEY_PAD1 );

	if( pad & PAD_INPUT_UP   ) input[P_UP   ]++;	else input[P_UP   ] = 0;
	if( pad & PAD_INPUT_DOWN ) input[P_DOWN ]++;	else input[P_DOWN ] = 0;
	if( pad & PAD_INPUT_LEFT ) input[P_LEFT ]++;	else input[P_LEFT ] = 0;
	if( pad & PAD_INPUT_RIGHT) input[P_RIGHT]++;	else input[P_RIGHT] = 0;
	if( pad & PAD_INPUT_A    ) input[P_A    ]++;	else input[P_A    ] = 0;
	if( pad & PAD_INPUT_B    ) input[P_B    ]++;	else input[P_B    ] = 0;	
}

// メニュー画面描画
void draw_menu( int select )
{
	const char menu[3][20] = {
		"ゲームスタート",
		"オプション",
		"終了",
	};
	static int white = GetColor( 255, 255, 255 );
	static int red = GetColor( 255, 0, 0 );

	for( int i=0; i<3; i++ ){
		// 現在カーソル上のメニューは赤、その他は白で描画
		DrawFormatString( 220, 300+20*i, (i==select)?(red):(white), "%s", menu );
	}
}



ちょっと遅かったか
コンパイルしてないのでコンパイルが通るか期待通り動くか怪しいですが参考までに
現在のy座標によって選択を変えると描画位置を変えたとき修正しないといけないので面倒かと思います
またこのままだとメニューの数が多くなるとメインループ内が見辛くなるので
機能ごとに関数なりクラスなりにまとめるといいかと思います

追記:間違いがやっぱりありましたので一部修正しておきました
   まだあるかもです

Eagle

Re:選択画面の作り方について

#6

投稿記事 by Eagle » 16年前

nayoさんもプログラムを改変してくれたんですね!

解決にしていましたが、参考プログラムは多いほうが勉強になります。

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

閉鎖

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