ページ 11

東方ProjectのMusic Roomの再現について

Posted: 2013年6月29日(土) 17:47
by Rittai_3D
この間はお世話になりました。3Dです。
今回も前回と同じ様な質問です。

前回、CSVファイル(最終的に独自フォーマット(?)のテキストファイル)からパス、曲名、コメントを読みとって
表示するプログラムに関して教えて頂きました。この場をお借りしてお礼申し上げます。今回は、読みとり部では無く、
表示部に関する質問です。

コード:

#define _CRT_SECURE_NO_WARNINGS 1
#include "DxLib.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MUSIC_MAX 17 // 17曲あります
#define DRAW_MAX  10 // 一度に表示する項目は10です

typedef struct{
	int color;
	char name[256];
}test_t;
// テスト用の構造体です

static 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;
}

int ProcessLoop() // 毎回行う重要なループ
{
	if( ProcessMessage()  != 0 ) return 1;
	if( ClearDrawScreen() != 0 ) return 1;
	if( gpUpdateKey()     != 0 ) return 1;
	return 0;
}

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int)
{
	AllocConsole(); // DOS窓を使う為の処理?
	freopen( "CONOUT$", "w", stdout ); // 上同様
	ChangeWindowMode( TRUE ),SetAlwaysRunFlag( TRUE ),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK ); // いつもの処理

	int i; // forで使用
	int SelectNum      = 0;		// 現在選択中
	int SelectMusicCmt = 0;		// 現在表示している曲のコメント
	int SelectedMusicNo= 0;		// コメントを表示する曲の番号を保持
	int Start = 0;				// 開始位置
	int End = 0;				// 描写終了位置
	int flag = 0;				// 選択している項目が10より大きい時のフラグ

	test_t music[17] = { // 構造体
		{ GetColor(240,210,210), "曲1~kyoku 1.", },
		{ GetColor(130,105,105), "曲2~kyoku 2.", },
		{ GetColor(130,105,105), "曲3~kyoku 3.", },
		{ GetColor(130,105,105), "曲4~kyoku 4.", },
		{ GetColor(130,105,105), "曲5~kyoku 5.", },
		{ GetColor(130,105,105), "曲6~kyoku 6.", },
		{ GetColor(130,105,105), "曲7~kyoku 7.", },
		{ GetColor(130,105,105), "曲8~kyoku 8.", },
		{ GetColor(130,105,105), "曲9~kyoku 9.", },
		{ GetColor(130,105,105), "曲10~kyoku 10.", },
		{ GetColor(130,105,105), "曲11~kyoku 11.", },
		{ GetColor(130,105,105), "曲12~kyoku 12.", },
		{ GetColor(130,105,105), "曲13~kyoku 13.", },
		{ GetColor(130,105,105), "曲14~kyoku 14.", },
		{ GetColor(130,105,105), "曲15~kyoku 15.", },
		{ GetColor(130,105,105), "曲16~kyoku 16.", },
		{ GetColor(130,105,105), "曲17~kyoku 17.", },
	};

	printf( "Start == %d, End == %d\n", Start, End ); // 初期値を出力
	while( !ProcessLoop() ){ // メインループ
		/* ------------------------------計算------------------------------ */

		End = Start + 10;

		if( Key[ KEY_INPUT_DOWN ] == 1 ){ // 下キーが押されたら
			SelectNum = ( SelectNum + 1 ) % MUSIC_MAX;

			if( flag == 1 ){
				Start++;  // 開始位置を移動する
				flag = 2; // フラグの値を変えて毎回行わないようにする
			}
		}

		if( Key[ KEY_INPUT_UP ] == 1 ){ // 上キーが押されたら
			SelectNum = ( SelectNum + ( MUSIC_MAX - 1 ) ) % MUSIC_MAX;

			if( flag == 1 ){
				Start--;  // 開始位置を下げる
				flag = 2; // フラグの値を変えて毎回行わないようにする
			}
		}

		if( Key[ KEY_INPUT_UP ] == 1 || Key[ KEY_INPUT_DOWN ] == 1 ){ // 上下どちらかのキーが押されたら
			for(i=0 ; i<MUSIC_MAX ; i++ ){
				if( i == SelectNum ){ // もし、現在処理している物が選択番号と同じなら
					music[i].color = GetColor(240,210,210); // 色を変える
				} else { // そうでなければ
					music[i].color = GetColor(130,105,105); // 色を変える
				}
			}
			if( SelectNum > DRAW_MAX ){ // もし、始まりが10曲より大きくなったら
				flag = 1; // フラグを立てる
			} else { // そうじゃ無ければ
				Start = 0; // 始まりを0に
				flag  = 0; // フラグを消す
			}

			printf( "Start == %d, End == %d, \n", Start, End ); // デバッグ用
		}

		if( Key[ KEY_INPUT_Z ] == 1 || Key[ KEY_INPUT_RETURN ] == 1 ){ // もし、エンターキーかZキーが押されたら
			SelectedMusicNo = SelectNum; // その時のSelectNumを保存
		}

		/* ------------------------------描写------------------------------ */

		for(i=Start ; i<End ; i++ ){ // No.~の部分
			if( i == SelectNum ){ // もし選択中なら
				DrawFormatString( 60, 100+16*i, music[i].color, "%s", music[i].name );
			} else { // そうで無ければ
				DrawFormatString( 65, 100+16*i, music[i].color, "%s", music[i].name );
			}
		}

		// コメント描写
		DrawFormatString( 80, 350, GetColor( 255, 255, 255 ), "%s", music[ SelectedMusicNo ].name ); //name なのは無視してください

		ScreenFlip();
	}

	DxLib_End();
	return 0;
}
となっております。
自分で実装したい事は、

No.1からNo.10までを表示。(表示中の曲番号 : No.1 ~ No.10)

もし、No.10選択中に下キーが押されたら、項目を一つずらして表示(表示中の曲番号 : No.2 ~ No.11)このとき、座標は固定で、項目だけを移動させたいです。

上同様に、たとえば、n曲~n+9曲表示中、選択されている項目がn+9曲の時に下キーが押されたら、表示中の項目はn+1曲~n+10曲となります。(伝えづらい...)

もし、No.17選択中に下キーが押されたら、最初の表示に戻す(表示中の曲番号 : No.1 ~ No.10)

としたいです。自分なりに書いてみましたが、うまくスクロール(?)しません。文字の色も変わりません。また、座標は変えずに項目を動かしたいのですが、全体的に動いてしまいます。(flag == 1の時)

自分の説明不足や質問で不明な点が有れば書いて頂けるとうれしいです。

[開発環境]
Visual C++ 2008 Express Edition
Dxlib
windows XP

[追記]
#タイトルを変更しました

Re: 東方ProjectのMusic Roomの再現について

Posted: 2013年6月29日(土) 19:29
by softya(ソフト屋)
前回のが尻切れトンボですが確認されたのでしょうか?

で、今回のはデバッガで変数の動きを追いかけましたか? また、ちゃんと調べていない気がするんですが。

Re: 東方ProjectのMusic Roomの再現について

Posted: 2013年6月29日(土) 19:39
by Rittai_3D
>>softya様

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

>前回のが尻切れトンボですが確認されたのでしょうか?

今から返信します。すいません、確認してませんでした。

>で、今回のはデバッガで変数の動きを追いかけましたか? また、ちゃんと調べていない気がするんですが。

一応、必要だと思った変数は追いかけました。変数の値が変だということはなかったです。

Re: 東方ProjectのMusic Roomの再現について

Posted: 2013年6月29日(土) 20:01
by non
位置がずれるのは、ここのiの考え方

コード:

        for(i=Start ; i<End ; i++ ){ // No.~の部分
            if( i == SelectNum ){ // もし選択中なら
                DrawFormatString( 60, 100+16*i, music[i].color, "%s", music[i].name );
            } else { // そうで無ければ
                DrawFormatString( 65, 100+16*i, music[i].color, "%s", music[i].name );
            }
        }
 
うまくスクロールしないのはflagを変更させるタイミングの問題。もう一度流れを整理すること。

Re: 東方ProjectのMusic Roomの再現について

Posted: 2013年6月29日(土) 20:41
by Rittai_3D
>>non様

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

>位置がずれるのは、ここのiの考え方

それ以外に思いついた方法だと、y座標固定の配列を用意して、項目を代入して行く、ですが、この方法だと、手間がかかりすぎてしまうのでは?と思い、もっと処理の楽なこの方法でしました。

やはり、y座標固定の方がいいのでしょうか?

>うまくスクロールしないのはflagを変更させるタイミングの問題。もう一度流れを整理すること

わかりました。明日プログラムの流れを整理したいと思います。まだテスト1日残っているので。

Re: 東方ProjectのMusic Roomの再現について

Posted: 2013年6月29日(土) 20:43
by non
このようにしてみたら

コード:

        for(j=0,i=Start ; i<End ;j++, i++ ){ // No.~の部分
            if( i == SelectNum ){ // もし選択中なら
                DrawFormatString( 60, 100+16*j, music[i].color, "%s", music[i].name );
            } else { // そうで無ければ
                DrawFormatString( 65, 100+16*j, music[i].color, "%s", music[i].name );
            }
        }

Re: 東方ProjectのMusic Roomの再現について

Posted: 2013年6月30日(日) 10:54
by Rittai_3D
>>non様

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

>このようにしてみたら

おおおおお!すごいです!自分の思ってた事が出来ました!

forってこんな使い方が出来るんですね。勉強になりました。

Re: 東方ProjectのMusic Roomの再現について

Posted: 2013年7月01日(月) 19:53
by Rittai_3D
こちらのトピックは、"CSVファイルからの読み込み"が完全に終わったら再開したします。