タイトル→メニュー(選択)画面→ゲーム の流れについて

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

タイトル→メニュー(選択)画面→ゲーム の流れについて

#1

投稿記事 by みやび » 8年前

C言語初心者です。
掲示板の質問を参考にしながらゲームをつくっています。
タイトルから選択画面に移り、ゲームをスタートするという流れをつくっているのですが、

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey(){
	char tmpKey[256]; // 現在のキーの入力状態を格納する
    GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
    for( int z=0; z<256; z++ ){ 
        if( tmpKey[z] != 0 ){ // z番のキーコードに対応するキーが押されていたら
            Key[z]++;     // 加算
        } else {              // 押されていなければ
            Key[z] = 0;   // 0にする
        }
    }
    return 0;
}

//  画面状態の定数
enum {
    STATE_TITLE,    //タイトル画面
    STATE_SELECT,   //選択画面
    STATE_MAIN,     //メイン画面
    STATE_END,      //ゲーム終了
};

//-------------------------------------------------
//  タイトル画面
//-------------------------------------------------

int Font = CreateFontToHandle( "MS ゴシック", 25,  5, DX_FONTTYPE_ANTIALIASING_EDGE ) ;	//"MSゴシック"の25pt,太さ5のフォントを作成

int title()
{
    DrawStringToHandle( 150, 200, "Please Push Enter", GetColor(255,255,255), Font );

    if(Key[KEY_INPUT_RETURN]==1) return TRUE;    //Enterが押されたらTRUE
    return FALSE;   //Enterが押されなければFALSE

}
 
//-------------------------------------------------
//  選択画面
//-------------------------------------------------
 
// メニュー項目の表示に必要な構造体を用意する
typedef struct{
        int x, y;       // 座標格納用変数
        char name[128]; // 項目名格納用変数
} MenuElement_t ;
 
//  選択画面
int select()
{
    //  メニュー項目要素を作る
    #define SELECT_NUM  3
    static MenuElement_t MenuElement[SELECT_NUM]={
                {  80, 150, "ゲームスタート" }, 
                { 100, 200, "タイトルに戻る" },
                { 100, 250, "ゲーム終了" },
        };
    static int SelectNum = 0; // 現在の選択番号
    
    // 計算フェーズ 
    if( Key[ KEY_INPUT_DOWN ] == 1 ){ // 下キーが押された瞬間だけ処理
        SelectNum = ( SelectNum + 1 ) % SELECT_NUM; // 現在の選択項目を一つ下にずらす(ループする)
    }

    if( Key[ KEY_INPUT_UP ] == 1 ){ // 上キーが押された瞬間だけ処理
        SelectNum = ( SelectNum + SELECT_NUM - 1 ) % SELECT_NUM; // 現在の選択項目を一つ上にずらす(逆ループする)
    }

    if( Key[ KEY_INPUT_DOWN ] == 1 || Key[ KEY_INPUT_UP ] == 1 ){ // 下キーか、上キーが押された瞬間
        for( int i=0; i<SELECT_NUM; i++ ){             // メニュー項目数である3個ループ処理
            if( i == SelectNum ){          // 今処理しているのが、選択番号と同じ要素なら
                MenuElement[i].x = 80; // 座標を80にする
            } else {                       // 今処理しているのが、選択番号以外なら
                MenuElement[i].x = 100;// 座標を100にする
            }
        }
    }
 
    // 描画フェーズ
    DrawString(60,100,"選択画面 (上下で選んで、Enterで決定)",GetColor(255,255,255));

    for( int i=0; i<SELECT_NUM; i++ ){ // メニュー項目を描画
        DrawFormatString( MenuElement[i].x, MenuElement[i].y, GetColor(0,255,255), MenuElement[i].name );
    }
    
    //  Enterボタンで選択
    if(Key[KEY_INPUT_RETURN]==1) {
        switch( SelectNum ) {
        case 0://ゲームスタート
            return STATE_MAIN;
            
        case 1://タイトルに戻る
            return STATE_TITLE;
            
        case 2://ゲーム終了
            return STATE_END;
        
        }
    }
    
    return STATE_SELECT;    //状態継続
}
 
//-------------------------------------------------
//  ゲームメイン
//-------------------------------------------------

 int x=10, y=10;

//  ゲームメイン
int gmain()
{
     DrawFormatString( x, y, GetColor(0,255,255), "座標[%d,%d]", x, y ); // 文字を描画する

     x = x + 2; // x座標を2加算
     y = y + 1; // y座標を1加算
    
    if(Key[KEY_INPUT_RETURN]==1) return TRUE;    //ENTERが押されたらTRUE
    return FALSE;   //ENTERが押されなければFALSE
}
 
//-------------------------------------------------
//  メインループ
//-------------------------------------------------

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
    ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    //  現在の状態
    int state = STATE_TITLE;
 
    // while(裏画面を表画面に反映, メッセージ処理, 画面クリア, キーの更新)
    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 && (state!=STATE_END)){
        
        switch( state ) {
        case STATE_TITLE:       //タイトル画面
            //  タイトル
            if( title() ) {
                //  なにか押されたら選択画面へ
                state = STATE_SELECT;
            }
            break;
            
        case STATE_SELECT:      //選択画面
            //  選択画面
            state = select();//戻りが画面状態
            break;
        
        case STATE_MAIN:        //メイン画面
            //  ゲームメイン
            if( gmain() ) {
                //  終了したらタイトルへ
                state = STATE_TITLE;
            }
            break;
            
        }
    }
 
    DxLib_End(); // DXライブラリ終了処理
    return 0;
}
今のプログラムだと、ゲームを終了してもう一度スタートすると途中からの処理になるのですが、
これをまた初めからゲームを処理するようにしたいです。

それと、タイトルでフォントのサイズなどを設定ているのですが、それが反映されていないようでした。
どこをどのように変えたらよいでしょうか??

nil
記事: 428
登録日時: 8年前

Re: タイトル→メニュー(選択)画面→ゲーム の流れについて

#2

投稿記事 by nil » 8年前

途中からの処理とは具体的に言うならばどのあたりなのでしょうか?

また、

コード:

        //  92行目辺り
        switch( SelectNum ) {
        case 0://ゲームスタート
            return STATE_MAIN;
            
        case 1://タイトルに戻る
            return STATE_TITLE;
            
        case 2://ゲーム終了
            return STATE_END;
        
        }
switch を用いた場合は break を使いましょう。

みやび

Re: タイトル→メニュー(選択)画面→ゲーム の流れについて

#3

投稿記事 by みやび » 8年前

このプログラムを実行してゲームスタートを押すと座標が右下にすすむプログラムが実行されます。
その座標が真ん中あたりに来たときにEnterを押してタイトルに戻り、
再びメニューからゲームスタートを押すと、座標がさきほど終了した真ん中あたりから処理されるということです。
これを続きからの処理ではなく、リスタートしたときも最初にスタートしたときと同じように最初の位置から座標をスタートさせたいという意味です。

ゲームを終了させたら初期値に戻す処理をすればいいと思ったのですが、やり方が分からなかったので質問させていただきました。

nil
記事: 428
登録日時: 8年前

Re: タイトル→メニュー(選択)画面→ゲーム の流れについて

#4

投稿記事 by nil » 8年前

そういうことであれば、
STATE_SELECT
のに、初期化処理を挿入してやればいいかと思います。

これは一例ですが、

コード:

        case STATE_SELECT:      //選択画面
            //  選択画面
            state = select();//戻りが画面状態

            x = 10;            //  それぞれの座標を初期化
            y = 10;            //  メインが終わった直後は、x,yともに以前の値になっているので、初期化してやります。

            break;

        case STATE_MAIN:        //メイン画面
             ………………
こういうものはどうでしょう?

アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: タイトル→メニュー(選択)画面→ゲーム の流れについて

#5

投稿記事 by パコネコ » 8年前

Fontが適用されていないようですが、それはDxライブラリの初期化を行うプログラムよりも先に作成されているためかと、思われます。
よって、

コード:

//-------------------------------------------------
//  タイトル画面
//-------------------------------------------------
 
int Font = CreateFontToHandle( "MS ゴシック", 25,  5, DX_FONTTYPE_ANTIALIASING_EDGE ) ; //"MSゴシック"の25pt,太さ5のフォントを作成

では、フォントの作成は行わず宣言のみにし、

コード:

//-------------------------------------------------
//  メインループ
//-------------------------------------------------
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
    ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    //  現在の状態
    int state = STATE_TITLE;
 
  
ここらへんで、フォントデータを作成してあげれば適用されると思われます。
(ループ内に作らないように注意です)

コード:


        case STATE_MAIN:        //メイン画面
            //  ゲームメイン
            if( gmain() ) {
                //  終了したらタイトルへ
                state = STATE_TITLE;
            }
  
ここらへんで、すべてのデータを初期化(正確には初期化とは言わないかな?)してあげれば、タイトルに戻ったときに起動時と同じ動作をしてくれると思われます。
(すべてのデータといってもいくつかは、変更しなくてもいいデータがありますが・・・)
それと、初期化を行うプログラムは、ひとつの関数にまとめてあげたほうが、いい処理だと思います。
(あとでタイトルに戻る処理が増えたときにも対応できますし・・・)

***************
あ、投稿おそかったっぽくて最後のほうは意味なくなってるかもです。
ニャン!!\(゜ロ\)(/ロ゜)/

みやび

Re: タイトル→メニュー(選択)画面→ゲーム の流れについて

#6

投稿記事 by みやび » 8年前

涼雅さん、パコネコさんありがとうございます!
おかげでゲームもフォントも思うような動作をしてくれるようになりました。
この考え方で他にもあった疑問もだいぶ解決することができました。

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

閉鎖

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