龍神録のタイトル画面の表示と遷移

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

龍神録のタイトル画面の表示と遷移

#1

投稿記事 by mi_l » 12年前

龍神録を作ってアレンジまでしたいと思っています。
C++の勉強もしていますが一旦こちらに・・・


今回はタイトルとそれからの遷移を表現したいと思っているのですが、考え方が今一わかりません。

※長文になります

一応まず、私の考えを載せます

コード:

typedef struct 
{
	int num;//番号 1->スタート、2->遊び方・・のように・
	int flag;//フラグ
	int brt;//輝度
	int img[MAX_TITLE]//選択するべき項目の画像表示個数
	int img_icon;//現在選択している項目の左隣にでも表示するアイコン
	int title_cnt;//カウント
}title_t;

//graph.cpp
void graph_title()
{
	int i = title.num;
	if(title.flag > 0)
	{
		SetDrawBlendMode(DX_BLENDMODE_ALPHA , title.brt);//輝度のセット
		for(i=0 ; i<MAX_TITLE ; i++)
		{
			DrawGraph(100 , 100+(i*100) , title.img[i] , TRUE);//選択するべき項目の画像
		}
		DrawGraph(100 , 100+(title.num) , title.img_icon , TRUE);//アイコン
	}
	else if(title.flag == 0)
		SetDrawBlendMode(DX_BLENDMODE_NOBLEND , 0);//暗く

}

//calc.cpp
void calc_title()
{
	if(stage == 0)//初期化状態だったら
	{
		title.flag = 1;//タイトル画面表示
	}

	if(title.cnt > 250 && title.brt <= 250)
		title.brt+= 2;//少しずつ明るく

	if(CheckStatePad(configpad.down) > 0)//↓キーが押されていたら
	{
		if(title.num <= MAX_TITLE)
			title.num += 1;
		else
			title.num += 0;
	}
	if(CheckStatePad(configpad.up) > 0)//↑キーが押されていたら
	{
		if(title.num >= 0)
			title.num -= 1;
		else
			title.num -= 0;
	}

	if(title.num <= MAX_TITLE && title.num >= 0)//選択すべき表示画像は2つだけなのでMAX_TITLEは今の段階では2です
	{
		if(CheckStatePad(configpad.slow) > 0)//左シフトキーが押されていたら(決定の意)
		{
			if(title.brt >= 0 )
				title.brt -= 2;//徐々に暗く

			switch(title.num)//タイトル画面の画像表示は背景と「スタート」、「遊び方」の二つだけ
			{
			case 1://スタートだったら
				if(title.brt <= 0)//完全に暗くなったら
				{
					/*ゲームを始める処理*/
					title.flag = 0;//タイトル画面を消す(真っ暗になってからなので実際に消えるところは見えませんが・・)
				}
				break;
				
			case 2://遊び方だったら
				/*同様に(今の時点ではここは無視)*/
				break;
			default:
				break;
			}
		}
	}
}
memsetでの初期化など、無駄なところは端折ってしまいましたが、やりたいことを説明します。

1、起動すると初めにタイトル表示
1-1、真っ暗から徐々に明るくなっていき、タイトル画面があらわれる
2、上下キーで選択(今のところは「スタート」と「遊び方」の二つだけ)
3、左シフトキーで決定
3-1、決定すると徐々に暗くなっていく
4、完全に暗くなったら、今まで通りゲーム画面に移る
4-1、そしてタイトル画面も消す

という流れなのですが、

遷移の部分がどうしてもわかりません(calc.sppのswitch文の中)あと、mainの書き方も・・・


考え方、助言お願いします。

また、私の説明不足で理解できなかった個所があれば、書いてください。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 龍神録のタイトル画面の表示と遷移

#2

投稿記事 by softya(ソフト屋) » 12年前

前回の設計とは? とか完全にすっ飛ばした内容ですね。
タスクシステムを使うとか、デザインパターンを使うとか色々と設計で考えべき所だと思うのですが。
変数のスコープも何か怪しいです。stage ってタイトル処理が参照する必要があるんでしょうか?
状態を管理する変数(状態遷移の管理変数)とカウンタを分離していないのも色々とまずい → 分かりづらい & バグりやすい。
ちなみに、numは個数を数えるのに使って、noは何番目を表すのに使います。こういう使い分けにも気をつけみてください。

あと
> 背景をスクロールさせて、キャラを出すところまでとりあえずやるつもりです!
これ中途半端なままですけど。良いんでしょうか?
今回のコードを見て思うことは理解が中途半端な部分が多く、原因は色んな所にちょっとづつ手をつけては放置していることに有るのでは?と思いました。
ちゃんと終わらせた方が今後のためには良いように思います。

【追記】
> C++の勉強もしていますが一旦こちらに・・・

C++は一旦置いとくんですね。
それでもC言語のモジュール設計として問題が有ると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mi_l

Re: 龍神録のタイトル画面の表示と遷移

#3

投稿記事 by mi_l » 12年前

なんか少し考えてみて書き換えてみたら普通にできました。

お手数かけました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 龍神録のタイトル画面の表示と遷移

#4

投稿記事 by softya(ソフト屋) » 12年前

苦言になりますが、今まで繰り返されている質問の事を考えるともっとプログラムの組み方そのものに拘って作る必要がありそうです。
今の動いたらOKと言うのはご自身の為になっていないんだと私は思っています。

ちゃっちゃっと書いたコードですが、こんな書き方をしないとメンテナンス性がすごく悪くて苦労することになります。

コード:

#include "DxLib.h"

#define MAX_TITLE 2

int Key[256]; // キーが押されているフレーム数を格納する

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

//	タイトル状態
enum TitleState_e  {
	TITLE_FADEIN,	//1-1、真っ暗から徐々に明るくなっていき、タイトル画面があらわれる
	TITLE_SELECT,	//2、上下キーで選択(今のところは「スタート」と「遊び方」の二つだけ)、左シフトキーで決定
	TITLE_FADEOUT,	//3-1、決定すると徐々に暗くなっていく
	TITLE_END,		//4、完全に暗くなったら、今まで通りゲーム画面に移る。そしてタイトル画面も消す
};

//	タイトル管理構造体
typedef struct {
	int selno;		//番号 0->スタート、12->遊び方・・のように・
	enum TitleState_e state;	//タイトル状態
	int cntCount;	//制御カウント
	int brt;		//輝度
//	int img[MAX_TITLE]//選択するべき項目の画像表示個数
//	int img_icon;	//現在選択している項目の左隣にでも表示するアイコン
} title_t;

//	実体
static title_t title;

//	title.cpp

//	初期化
void init_title()
{
	title.selno = 0;			//番号
	title.state = TITLE_FADEIN; //タイトル状態
	title.cntCount = 0; 		//制御カウント
	title.brt = 0;				//輝度
}

//	描画
void graph_title()
{
	static char *msg[2] = {"スタート","遊び方"};
	SetDrawBlendMode( DX_BLENDMODE_ALPHA , title.brt ); //輝度のセット
	for( int i=0 ; i<MAX_TITLE; i++ ) {
//		DrawGraph( 100 , 100 + ( i * 100 ) , title.img[i] , TRUE ); //選択するべき項目の画像
		if( i == title.selno ) {
			DrawFormatString( 100 , 100+(i*100) , GetColor(255,255,255), msg[i] );
		} else {
			DrawFormatString( 100 , 100+(i*100) , GetColor(0,0,255), msg[i] );
		}
	}
//	DrawGraph( 100 , 100 + ( title.selno ) , title.img_icon , TRUE ); //アイコン
	SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 255 ); //もとに戻す
}

//	更新
int update_title()
{
	//	状態別の処理
	switch( title.state ) {
	case TITLE_FADEIN:
		//	徐々に明るく。
		title.cntCount++;
		title.brt = title.cntCount * 3;
		//	上限?
		if( title.brt >= 255 ) {
			//	明るさ固定して状態遷移
			title.brt = 255;
			title.state = TITLE_SELECT;//選択
		}
		break;
		
	case TITLE_SELECT:
		//	メニュー選択
		if(Key[KEY_INPUT_DOWN]==1)	{//下キーが押されていたら
			title.selno++;
			if( title.selno >= MAX_TITLE ) {
				title.selno = MAX_TITLE-1;
			}
		}
	    if(Key[KEY_INPUT_UP]==1){//上キーが押されていたら
			title.selno--;
			if( title.selno < 0  ) {
				title.selno = 0;
			}
	    }
		//	決定処理
	    if(Key[KEY_INPUT_RETURN]==1){//RETURNキーが押されていたら
	    	//	決定したので、次に遷移
	    	title.state = TITLE_FADEOUT;	//タイトル状態
			title.cntCount = 0; 			//制御カウント
	    }
		break;
		
	case TITLE_FADEOUT:
		//	徐々に暗く。
		title.cntCount++;
		title.brt = 255 - title.cntCount * 3;
		//	下限?
		if( title.brt <= 0 ) {
			//	明るさ固定して状態遷移
			title.brt = 0;
			title.state = TITLE_END;//終了
		}
		break;
		
	case TITLE_END:
		//	終了
		return 1;
		break;
	}
	
	//	継続
	return 0;
}

//	メインの状態
enum MainState_e {
	MAIN_TITLE,
	MAIN_GAME,
};

//	main
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
	
	//	メインの状態を初期化
	enum MainState_e mainState = MAIN_TITLE;
	
	//	タイトル初期化
	init_title();
	
	// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
		
		//	キーの更新
		gpUpdateKey();
		
		switch( mainState ) {
		case MAIN_TITLE:
			//	タイトル処理
			if( update_title() ) {
				mainState = MAIN_GAME;	//次からゲームに遷移する
			}
			graph_title();
			break;
		case MAIN_GAME:
			//	メイン処理
			DrawFormatString( 100 , 100, GetColor(255,255,255), "今はゲーム画面だ" );
			break;
		}
	}

	DxLib_End(); // DXライブラリ終了処理
	return 0;
}

by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mi_l

Re: 龍神録のタイトル画面の表示と遷移

#5

投稿記事 by mi_l » 12年前

返信ありがとうございます。

なんか、コードまで書いてくれてありがとうございます。

今も新たな要素を追加しているところです。

そこで、ソフト屋さんの書いていただいたコードと、私の書いたコードを比較すると、書き方はほぼ同じで自分でも驚いています!!


「スタート」、「遊び方」は画像なのと、enumは使っておらず、初期化はmemsetでやっているというところが把握できている大きな違いです・・・

やりたかった処理(徐々に明るく・・・・など)もしっかりできましたしなんか嬉しいです。


それと、enum(列挙型)についてなのですが、どういうものかはわかります。

ですが、具体的にどういう時に便利か、使った方がいいか、というサンプルコードを見たことがありません・・・(printfで値を返す・・くらいのしか見たことがありません)
どこか、載っているサイトなどあれば、教えてください。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 龍神録のタイトル画面の表示と遷移

#6

投稿記事 by softya(ソフト屋) » 12年前

前のは変数のスコープとか適当で怪しかったんですが大丈夫ですか?
そこを見落として同じに見えていたらかなり危険だと思います。

あとmemsetは将来のC++を考えて使わないほうが良いです。

>それと、enum(列挙型)についてなのですが、どういうものかはわかります。
>ですが、具体的にどういう時に便利か、使った方がいいか、というサンプルコードを見たことがありません・・・(printfで値を返す・・くらいのしか見たことがありません)

これが、その例なんですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mi_l

Re: 龍神録のタイトル画面の表示と遷移

#7

投稿記事 by mi_l » 12年前

返信ありがとうございます。

memsetを推奨しない理由って説明したら長くなりますか?

確かにC++でしたらコンストラクタで初期化しているのでmemsetは使っていませんが・・・


enumの例ですが、最初の例としては、私には少しレベルが高いです・・・できればもう少し簡易的な例がいいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 龍神録のタイトル画面の表示と遷移

#8

投稿記事 by softya(ソフト屋) » 12年前

>memsetを推奨しない理由って説明したら長くなりますか?
C++的な理由はC++のクラスのコンストラクト後の変数まで0クリアされてしまうからです。
C言語で言えば、大雑把すぎる初期化なので明確に書く癖を付けたほうが良いと思います。
大抵は上手く動きますが、enum変数の初期化が正規の方法ではないのでガードが働かない問題があります。

>enumの例ですが、最初の例としては、私には少しレベルが高いです・・・できればもう少し簡易的な例がいいです。
ご自分で検索してみてください。私には、どの位が程良いのかつかめません。
ただ、使ってみないことにはenumの使い所を理解することは出来ないないですよ。
#defineとの大きな違いは、置換の誤動作を避けれることと追加などのメンテナンス性の良さです。

「Programming Place Plus C言語編 第50章 列挙型、共用体、ビットフィールド」 一応の参考。
http://www.geocities.jp/ky_webid/Progra ... html#start

【補足】 前のコードの事を考えると変数のスコープを上手く処理できているか不安が有るので、コードを見せてもらった方が良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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