ページ 11

東方紅魔郷のタイトル画面の項目について

Posted: 2015年2月22日(日) 14:24
by けんい
件名の通り東方紅魔郷のタイトル画面の項目についてです。

質問文
"自分が今行いたい事は何か、今何がわからないのか、知りたいのか"
東方紅魔郷のタイトル画面の項目についてで、紅魔郷のタイトルの項目は選択された項目が赤くなりますよね?
それの仕組みと実装方法が知りたいです。

"どのように取り組んだか(プログラムコードがある場合記載)"
自分は↓キーが押されたら背景の上から
”選択されている項目の下の項目が赤くなった画像”を重ねているのかと考えています。
取り組んだ内容としては、case20から↓キーを押したらcase21(新しく作ったもの)へ飛び、
そこで”選択されている項目の下の項目が赤くなった画像”を描画したりしました。
が、これではcase20へもどれませんでした。
(下のコードは上文の”取り組んだ~せんでした。”のものではありません。)

プログラミングについては龍神録プログラミングの館、新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]
タイトルの画面の作り方は"http://dixq.net/forum/viewtopic.php?f=3&t=14407"ここを参考にしました。

main.cpp

コード:

#define GLOBAL_INSTANCE 
#include "../include/GV.h"

//ループで必ず行う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){//メインループ

		static int sel = 0;//追加
        static int x = 500 ,y = 100;//追加
		static int title = LoadGraph("dat/titlea.png"); // タイトル画像ハンドル

 
		music_ini();
        switch(func_state){
            case 0://初回のみ入る処理
                load();     //データロード
                first_ini();//初回の初期化
                func_state=98;//ここを98に
                break;
            case 98://STGを始める前に行う初期化
                ini();
                load_story();
                func_state=99;//メニューへ
                break;
            case 99://メニュー
				DrawGraph( 0 , 0 , title , FALSE ) ;      //タイトル表示

                DrawString(x , y , "Gamestart" , GetColor(255,255,255) , 0);
                DrawString(x , y+30 , "weit" , GetColor(255,255,255) , 0);
                DrawBox(x-30,y+(sel*30),x-10,y+20+(sel*30) , GetColor(100,92,161) ,true);
 
                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel > 0)
                        sel--;
                    else
                        sel = 0;
                }
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        sel++;
                    else
                        sel = 1;
                }
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
            case 100://通常処理
                calc_ch();   //キャラクタ計算
                ch_move();   //キャラクタの移動制御
                cshot_main();//自機ショットメイン
				enemy_main();//敵処理メイン
				shot_main(); //ショットメイン
				boss_shot_main();
				out_main();  //当たり計算
				effect_main();//エフェクトメイン
                graph_main();//描画メイン
				if(boss.flag==0)
	                stage_count++;
                break;
            default:
                printfDx("不明なfunc_state\n");
                break;
        }
		music_play();
        if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break;//エスケープが入力されたらブレイク
        ScreenFlip();//裏画面反映
		count++;
    }

    DxLib_End();//DXライブラリ終了処理
    return 0;
}
これは私の現在のmain.cppのなかです。
また、龍神録プログラミングの館の24章を現在しています。

環境  
Windows7 64bit
コンパイラ名 : VC++ 2008EE

"どの程度C言語を理解しているか"
初めて1ヶ月ぐらいであるためそこまで理解できていないと思います。

追記
言語はC++(Cpp)です。

Re: 東方紅魔郷のタイトル画面の項目について

Posted: 2015年2月22日(日) 17:17
by Rittai_3D
自分は↓キーが押されたら背景の上から
”選択されている項目の下の項目が赤くなった画像”を重ねているのかと考えています。
わたしは、選択されていないときの画像と、選択されているときの画像を両方用意して、項目が選択されているかどうかを判定し、
選択されているならば画像を選択中のものに、そうでないなら、選択されていないものに差し替える、だと思いました。
オフトピック
本家を確認したところ、選択されていない項目は、選択されていない画像をαブレンドしているだけに見えました。
取り組んだ内容としては、case20から↓キーを押したらcase21(新しく作ったもの)へ飛び、
そこで”選択されている項目の下の項目が赤くなった画像”を描画したりしました。
が、これではcase20へもどれませんでした。
その部分のコードを貼ってくださればなにかアドバイスができると思います。
オフトピック
メインループ内に

コード:

int main( void )
{
    while( 1 ) {
        static int a = 0;
    }
    return 0;
}
などとおくのではなく、単純に

コード:

int main( void )
{
   int a = 0;
   while( 1 ) {
   }
   return 0;
}
ではだめなのでしょうか?

Re: 東方紅魔郷のタイトル画面の項目について

Posted: 2015年2月22日(日) 18:01
by けんい
返信ありがとうございます。
取り組んだ内容としては、case20から↓キーを押したらcase21(新しく作ったもの)へ飛び、
そこで”選択されている項目の下の項目が赤くなった画像”を描画したりしました。
が、これではcase20へもどれませんでした。
これが作ってみたコードです。変更点のみコードを書いてます。それ以外は画像のロードしか変更していません。

コード:

       case 0://初回のみ入る処理
                load();     //データロード
                first_ini();//初回の初期化
                func_state=10;//ここを10に
                break;
            case 10://STGを始める前に行う初期化
                ini();
                load_story();
                func_state=20;//メニューへ
                break;
            case 20://メニュー
				DrawGraph( 0 , 0 , title , FALSE ) ;      //タイトル表示

                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel > 0)
                        sel--;
                    else
                        sel = 0;
                }
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        func_state=21;
                }
                break;
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
			case 21://メニュー2
				DrawGraph( 0 , 0 , title2 , FALSE ) ;      //タイトル表示

                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel > 0)
                        func_state=20;
                }
                break;
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        func_state=21;
                }
                break;
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
            case 100://通常処理
                calc_ch();   //キャラクタ計算
                ch_move();   //キャラクタの移動制御
                cshot_main();//自機ショットメイン
				enemy_main();//敵処理メイン
				shot_main(); //ショットメイン
				boss_shot_main();
				out_main();  //当たり計算
				effect_main();//エフェクトメイン
                graph_main();//描画メイン
				if(boss.flag==0)
	                stage_count++;
                break; 
ですがこれだと、case20,case21ともにZキーを押してもcase100へ行きません。
また、case21に行くとcase20へもどれませんでした。
アドバイスをお願いします。

Re: 東方紅魔郷のタイトル画面の項目について

Posted: 2015年2月22日(日) 18:29
by Rittai_3D

コード:

            case 20://メニュー
                DrawGraph( 0 , 0 , title , FALSE ) ;      //タイトル表示
 
                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel > 0)
                        sel--;
                    else
                        sel = 0;
                }
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        func_state=21;
                }
                break;
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
ここ(16行目)のbreakの意味を理解していますか?

Re: 東方紅魔郷のタイトル画面の項目について

Posted: 2015年2月22日(日) 19:17
by けんい
ここ(16行目)のbreakの意味を理解していますか?
あぁ!break は、switch 文から抜けるんでした。ありがとうございます。

コード:

      case 20://メニュー
				DrawGraph( 0 , 0 , title , FALSE ) ;      //タイトル表示

                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel > 0)
                        sel--;
                    else
                        sel = 0;
                }
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        func_state=21;
                }
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
			case 21://メニュー2
				DrawGraph( 0 , 0 , title2 , FALSE ) ;      //タイトル表示

                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel > 0)
                        func_state=20;
                }
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        func_state=21;
                }
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
            case 100://通常処理
                calc_ch();   //キャラクタ計算
                ch_move();   //キャラクタの移動制御
                cshot_main();//自機ショットメイン
				enemy_main();//敵処理メイン
				shot_main(); //ショットメイン
				boss_shot_main();
				out_main();  //当たり計算
				effect_main();//エフェクトメイン
                graph_main();//描画メイン
				if(boss.flag==0)
	                stage_count++;
                break;
こうコードを書き換えることでZキーでcase100へいけました。
つぎはcase20とcase21のループのさしかた(whileやforの組み込み方?)について教えていただきたいのですが。
(図々しいですがすみません。)

Re: 東方紅魔郷のタイトル画面の項目について

Posted: 2015年2月22日(日) 19:29
by けんい
私の返信を読んでいるまたはそれに返信を書いている途中かもしれませんがすいません。
自己解決しました。 Rittai_3D 様 返信ありがとうございました。

完成したコードです。

コード:

            case 0://初回のみ入る処理
                load();     //データロード
                first_ini();//初回の初期化
                func_state=10;//ここを10に
                break;
            case 10://STGを始める前に行う初期化
                ini();
                load_story();
                func_state=20;//メニューへ
                break;
            case 20://メニュー
				DrawGraph( 0 , 0 , title , FALSE ) ;      //タイトル表示

                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel < 1)
                        func_state=21;
                }
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        func_state=21;
                }
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
			case 21://メニュー2
				DrawGraph( 0 , 0 , title2 , FALSE ) ;      //タイトル表示

                if(CheckStateKey(KEY_INPUT_UP)==1)
                {
                    if(sel < 1)
                        func_state=20;
                }
                if(CheckStateKey(KEY_INPUT_DOWN)==1)
                {
                    if(sel < 1)
                        func_state=20;
                }
                if(CheckStateKey(KEY_INPUT_Z)==1)
                {
                    if(sel == 0)
                        func_state=100;
                }
                break;
            case 100://通常処理
                calc_ch();   //キャラクタ計算
                ch_move();   //キャラクタの移動制御
                cshot_main();//自機ショットメイン
				enemy_main();//敵処理メイン
				shot_main(); //ショットメイン
				boss_shot_main();
				out_main();  //当たり計算
				effect_main();//エフェクトメイン
                graph_main();//描画メイン
				if(boss.flag==0)
	                stage_count++;
                break;