ハイスコアの表示方法について

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

ハイスコアの表示方法について

#1

投稿記事 by けんじん » 14年前

 初めまして。私は今、インベーダーもどきなゲームを作っています。しかし、ハイスコアをタイトル画面とゲームをプレイしている画面の両方に表示することができなくて詰まっています。

 「.cpp」のファイルが2個、「.h」のファイルは1個あります。「.cpp」のファイルは、タイトル画面を処理する方と、ゲームをプレイしているところを処理するために、2個になりました。

 下は、ゲームをプレイしているところを処理する方のプログラムです。

コード:

#include "DxLib.h"

#define X 15
#define Y 5

int NumberGraph[ 10 ];		// 数字グラフィックの識別番号を保存する配列
int SoundHandle[ 4 ], s;	// 敵の移動音の識別番号を保存する配列

// 数値Numをn桁までグラフィック表示する関数(x, yで座標指定)
void NumberDraw( int Num, int n, int x, int y ) ;

// ゲームの処理をする関数
void Game()
{
	int PlayerX, PlayerY, PlayerCount, PlayerGraph[3], PlayerMuteki;
	int EnemyX[X][Y], EnemyY[X][Y], EnemyGraph[2], EnemyPattern, EnemyMuki, EnemyMoveCounter, EnemyMoveSpeed;
	int EnemyAlive[X][Y], EnemyCount;
	int TurnLeft, TurnRight;
	int UfoX, UfoY, UfoGraph[2], UfoFlag, UfoDelay, UfoSound, UfoSoundDelay, UfoKilled ;
	int ShotX, ShotY, ShotGraph, ShotFlag;
	int EnemyShotX[X][Y], EnemyShotY[X][Y], EnemyShotDelay[X][Y], EnemyShotFlag[X][Y], EnemyShotGraph;
	int PlayerW, PlayerH, EnemyW, EnemyH, ShotW, ShotH, EnemyShotW, EnemyShotH, UfoW, UfoH;
	int GameOverFlag;
	int Score, ClearCount;
	int ColorWhite;
	int i, j ;

	// 数字グラフィックを分割読みこみ
	// 分割数は全部で10こ、1列当たり10個の分割数でそれが1行だけあるので
	// 以下のような記述になります。
	LoadDivGraph( "Graphic\\Number.png" , 10 , 10 , 1 , 16 , 16 , NumberGraph ) ;

	// 移動音をメモリへ読み込み
	s = 0;
	SoundHandle[0] = LoadSoundMem( "Sound\\move_1.wav" ) ;
	SoundHandle[1] = LoadSoundMem( "Sound\\move_2.wav" ) ;
	SoundHandle[2] = LoadSoundMem( "Sound\\move_3.wav" ) ;
	SoundHandle[3] = LoadSoundMem( "Sound\\move_4.wav" ) ;

	// プレイヤーのグラフィックをメモリにロード&表示座標セット
	LoadDivGraph( "Graphic\\Player.png" , 3 , 3 , 1 , 16 , 11 , PlayerGraph ) ;
	PlayerX = 248 ; PlayerY = 464 ;

	// プレイヤーの残機数をセット
	PlayerCount = 2 ;

	// プレイヤーが無敵かどうかを保持する変数を初期化
	PlayerMuteki = 0 ;

	// 敵のグラフィックをメモリにロード&表示パターンを初期化
	LoadDivGraph( "Graphic\\Enemy.png", 2 , 2 , 1 , 16 , 16 , EnemyGraph ) ;
	EnemyPattern = 0;

	// 敵のあらゆるデータを保持する変数の初期化
	for ( i = 0; i < X; i++ ) {
		for ( j = 0; j < Y; j++ ) {
			// 敵の表示座標をセット
			EnemyX[i][j] = 16 + i*32 ; 
			EnemyY[i][j] = 48 + j*32 ;

			// 敵の生存状態を表す変数に1(生存中)を代入する
			EnemyAlive[i][j] = 1;

			// 敵の弾が飛んでいるかどうかを保持する変数に『飛んでいない』を表す0を代入
			EnemyShotFlag[i][j] = 0 ;

			// 敵が弾を撃つタイミングを取るための計測用変数に0を代入
			EnemyShotDelay[i][j] = 0 ;
		}
	}

	// 敵の移動方向をセット
	EnemyMuki = 1 ;

	// 敵が一定周期で移動するように制御する変数を初期化&速度を制御する変数を初期化
	EnemyMoveCounter = 0, EnemyMoveSpeed = 1 ;

	// 敵の左右移動反転フラグをそれぞれ初期化
	TurnLeft = 0; TurnRight = 0;

	// 初期の敵の数を変数に保持する
	EnemyCount = X * Y;

	// 弾のグラフィックをメモリにロード
	ShotGraph = LoadGraph( "Graphic\\Shot.png" ) ;

	// 弾が画面上に存在しているか保持する変数に『存在していない』を意味する0を代入しておく
	ShotFlag = 0 ;

	// 敵の弾のグラフィックをメモリにロード
	EnemyShotGraph = LoadGraph( "Graphic\\EnemyShot.png" ) ;

	// UFOのグラフィックをメモリにロード
	LoadDivGraph( "Graphic\\Ufo.png", 2 , 2 , 1 , 32 , 16 , UfoGraph ) ;

	// UFOの移動音をメモリにロード
	UfoSound = LoadSoundMem( "Sound\\ufo.wav" ) ;

	// UFOが画面上に存在しているか保持する変数に『存在していない』を意味する0を代入しておく
	UfoFlag = 0 ;

	// UFOが出現するまでの時間を保持する変数を初期化
	UfoDelay = 0 ;

	// UFOの移動音を再生するまでの時間を保持する変数を初期化
	UfoSoundDelay = 0 ;

	// プレイヤーがUFOを殺したかどうかを保持する&
	// UFOが死んだ時の画像を表示する時間を保持する変数を初期化
	UfoKilled = 0 ;

	// プレイヤーのグラフィックのサイズを得る
	GetGraphSize( PlayerGraph[0] , &PlayerW , &PlayerH ) ;

	// 弾のグラフィックのサイズを得る
	GetGraphSize( ShotGraph , &ShotW , &ShotH ) ;

	// 敵の弾のグラフィックのサイズを得る
	GetGraphSize( EnemyShotGraph , &EnemyShotW , &EnemyShotH ) ;

	// 敵のグラフィックのサイズを得る
	GetGraphSize( EnemyGraph[0] , &EnemyW , &EnemyH ) ;

	// UFOのグラフィックのサイズを得る
	GetGraphSize( UfoGraph[0] , &UfoW , &UfoH ) ;

	// ゲームオーバーかどうかの状態を保持する変数に0を代入
	GameOverFlag = 0;

	// 白色の値を取得
	ColorWhite = GetColor( 255 , 255 , 255 ) ;

	// プレイヤーのスコアを保持する変数を初期化
	Score = 0;

	// ステージをクリアした数を保持する変数を初期化
	ClearCount = 0;

	// メインルーチン
	while ( 1 )
	{
		// 画面を初期化(真っ黒にする)
		ClearDrawScreen();

		// 画面右側等の描画
		{
			// スコア、残機を表示するところとの境界線を描画
			DrawLine( 16+32*X , 0 , 16+32*X , 480, ColorWhite );

			// 残機数だけ自機を描画し、残機数をプレイヤーに確認できるようにする
			for( i = 0; i < PlayerCount; i++ )
			{
				DrawGraph( 32+32*X + i*32, 480 - 16, PlayerGraph[0], FALSE );
			}

			// スコアを表示
			NumberDraw( Score, 7, 32+32*X, 100 );
		}

		// プレイヤーの操作ルーチン
		{
			// プレイヤーが無敵状態なら無敵状態を保持する変数を1減らす
			if( PlayerMuteki > 0 ) PlayerMuteki-- ;

			// ←キーを押していたら左に移動させる
			if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ) PlayerX -= 3 ;

			// →キーを押していたら右に移動させる
			if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) PlayerX += 3 ;

			// プレイヤーが画面左端からはみ出そうになっていたら画面内の座標に戻してあげる
			if( PlayerX < 0 ) PlayerX = 0 ;

			// プレイヤーが画面右端からはみ出そうになっていたら画面内の座標に戻してあげる
			if( PlayerX > 32*X ) PlayerX = 32*X  ;

			// スペースキーを押していて、かつ弾が撃ち出されていなかったら弾を発射する
			if( CheckHitKey( KEY_INPUT_SPACE ) == 1 && ShotFlag == 0 )
			{
				// 弾の位置をセット、位置はプレイヤーの中心にする
				ShotX = ( PlayerW - ShotW ) / 2 + PlayerX ;
				ShotY = ( PlayerH - ShotH ) / 2 + PlayerY ;

				// 弾は現時点を持って存在するので、存在状態を保持する変数に1を代入する
				ShotFlag = 1 ;
			}

			// プレイヤーを描画(無敵状態をならPlayerGraph[1]、そうでないならPlayerGraph[0]を表示)
			if ( PlayerMuteki > 0 )
			{
				DrawGraph( PlayerX , PlayerY , PlayerGraph[1] , TRUE ) ;
			} else {
				DrawGraph( PlayerX , PlayerY , PlayerGraph[0] , TRUE ) ;
			}
		}

		// 自機の弾の移動ルーチン( 存在状態を保持している変数の内容が1(存在する)の場合のみ行う )
		if( ShotFlag == 1 )
		{
			// 弾を16ドット上に移動させる
			ShotY -= 8 ;

			// 画面外に出てしまった場合は存在状態を保持している変数に0(存在しない)を代入する
			if( ShotY < -80 )
			{
				ShotFlag = 0 ;
			}

			// 画面に弾を描画する
			DrawGraph( ShotX , ShotY , ShotGraph , TRUE ) ;
		}

		// 敵の行動ルーチン
		{
			// 敵の数が減ってきたら速度を保持する変数を増やす
			EnemyMoveSpeed = 300 / EnemyCount;

			// 移動カウンターを速度を保持する変数分&クリア数を保持する変数分だけ増加
			EnemyMoveCounter += EnemyMoveSpeed + ClearCount*5;

			// 敵の移動カウンターが指定値を満たしたら移動する
			if( EnemyMoveCounter >= 240 )
			{
				// 敵の表示パターンを切り替える
				EnemyPattern++;
				EnemyPattern %= 2;

				// 移動音を順次再生
				PlaySoundMem( SoundHandle[s], DX_PLAYTYPE_BACK ) ;
				s++ ;
				if( s > 3 )	s = 0; 

				// 移動処理
				for( i = 0; i < X; i++ ) {
					for( j = 0; j < Y; j++ ) {
						// 敵の生存を表す変数が1なら移動
						if( EnemyAlive[i][j] == 1 )
						{
							// 移動カウンターをリセット
							EnemyMoveCounter = 0 ;

							// 敵の座標を移動している方向に移動する
							if( EnemyMuki == 1 ) EnemyX[i][j] += 4 ;
							if( EnemyMuki == 0 ) EnemyX[i][j] -= 4 ;

							// 敵が1体でも画面右端からでそうになっていたら、左に反転フラグをON
							if( EnemyX[i][j] > 32*X ) TurnLeft = 1;

							// 敵が1体でも画面左端からでそうになっていたら、右に反転フラグをON
							if( EnemyX[i][j] < 0 ) TurnRight = 1;
						}
					}
				}

				// 左に反転フラグが立っていたら、全ての敵を画面内の座標に戻し、移動する方向を左にさせ、下に一段移動する
				if( TurnLeft == 1 )
				{
					for( i = 0; i < X; i++ ) {
						for( j = 0; j < Y; j++ ) {
							// 敵の生存を表す変数が1なら移動
							if( EnemyAlive[i][j] == 1 )
							{
								EnemyX[i][j] -= 4;
								EnemyY[i][j] += 16 ;
							}
						}
					}
					
					// 敵の移動方向を保持する変数に0(左)を代入
					EnemyMuki = 0 ;

					// 左に反転フラグをOFFにする
					TurnLeft = 0;
				}

				// 右に反転フラグが立っていたら、全ての敵を画面内の座標に戻し、移動する方向を右にさせ、下に一段移動する
				if( TurnRight == 1 )
				{
					for( i = 0; i < X; i++ ) {
						for( j = 0; j < Y; j++ ) {
							// 敵の生存を表す変数が1なら移動
							if( EnemyAlive[i][j] == 1 )
							{
								EnemyX[i][j] += 4;
								EnemyY[i][j] += 16 ;
							}
						}
					}

					// 敵の移動方向を保持する変数に1(右)を代入
					EnemyMuki = 1 ;

					// 右に反転フラグをOFFにする
					TurnRight = 0;
				}
			}

			// 敵を描画
			for( i = 0; i < X; i++) {
				for (j = 0; j < Y; j++) {
					// 敵の生存状態を保持する変数が1なら描画
					if( EnemyAlive[i][j] == 1 )
						DrawGraph( EnemyX[i][j] , EnemyY[i][j] , EnemyGraph[ EnemyPattern ] , FALSE ) ;
				}
			}

			// 敵が弾を撃つ処理
			for( i = 0; i < X; i++ ) {
				for( j = 0; j < Y; j++ ) {
					// 弾が飛んでいない場合のみ、弾を撃つタイミングを計測するためのカウンターに代入
					if( EnemyShotFlag[i][j] == 0 && ClearCount <= 9 )
					{
						// 代入する値はランダム(クリアすればするほど範囲は狭まる=敵が弾を撃つ周期が狭まる)
						EnemyShotDelay[i][j] = GetRand( 5000 - ClearCount*500 ) ;
					}

					// もしカウンター変数がある値になり、かつ生きている場合は弾を撃つ処理を行う
					if( EnemyShotDelay[i][j] == 0 && EnemyAlive[i][j] == 1)
					{
						// もし既に弾が『飛んでいない』状態だった場合のみ発射処理を行う
						if( EnemyShotFlag[i][j] == 0 )
						{
							// 弾の発射位置を設定する
							EnemyShotX[i][j] = EnemyX[i][j] + EnemyW / 2 - EnemyShotW / 2 ;
							EnemyShotY[i][j] = EnemyY[i][j] + EnemyH / 2 - EnemyShotH / 2 ;

							// 弾の状態を保持する変数に『飛んでいる』を示す1を代入する
							EnemyShotFlag[i][j] = 1 ;
						}

						// 弾を打つタイミングを計測するための変数に0を代入
						EnemyShotDelay[i][j] = 0 ;
					}
				}
			}
		}

		// UFOの行動処理
		{
			// UFOが出現するまでの時間をカウント
			if( UfoFlag == 0 )	UfoDelay += GetRand( 100 );

			// UFOが存在していたら移動させる
			if( UfoFlag == 1 )
			{
				UfoX -= 2 ;

				// 移動音を再生するまでの時間を保持する変数を増加
				UfoSoundDelay ++ ;

				// 再生するまでの時間を保持する変数がある値以上になったら
				if( UfoSoundDelay >= 30 )
				{
					// UFO移動音を再生
					PlaySoundMem( UfoSound , DX_PLAYTYPE_BACK ) ;

					// 再生までの時間を保持する変数を初期化
					UfoSoundDelay = 0 ;
				}

				// UFOが画面左端から出そうになったら
				if( UfoX <= -32 )
				{
					// UFOが存在しているかどうかを保持する変数に「存在しない」を表す0を代入
					UfoFlag = 0 ;
				}

				// UFOを描画
				DrawGraph( UfoX, UfoY, UfoGraph[0], TRUE ) ;
			}
			
			// 出現するまでの時間が値を満たし、UFOが出現していなかったら
			if( UfoDelay >= 75000 && UfoFlag == 0 )
			{
				// UFOを出現させる
				UfoX = 640 ;	UfoY = 16 ;
				DrawGraph( UfoX, UfoY, UfoGraph[0], TRUE ) ;

				// UFOが出現するまでの時間を初期化
				UfoDelay = 0 ;

				// UFOが存在しているかどうかを保持する変数に「存在する」を表す1を代入
				UfoFlag = 1 ;
			}

			// もしプレイヤーにUFOが殺されたばかりなら
			if( UfoKilled > 0 )
			{
				// UFOが殺された時の画像を描画
				DrawGraph( UfoX, UfoY, UfoGraph[1], TRUE ) ;

				// UFOが殺されてどれぐらい経ったかを保持する変数を減らす
				UfoKilled -- ;
			}
		}

		// 敵の弾の処理
		{
			// 敵の弾の状態が『飛んでいる』場合のみ弾の移動処理を行う
			for( i = 0; i < X; i++ ) {
				for( j = 0; j < Y; j++ ) {
					if( EnemyShotFlag[i][j] == 1 )
					{
						// 少し下にずらす
						EnemyShotY[i][j] += 4 ;

						// もし弾が画面下端からはみ出てしまった場合は弾の状態を『飛んでいない』を現す0にする
						if( EnemyShotY[i][j] > 480 ) EnemyShotFlag[i][j] = 0 ;

						// 画面に描画する( EnemyShotGraph : 敵の弾のグラフィックのハンドル )
						DrawGraph( EnemyShotX[i][j] , EnemyShotY[i][j] , EnemyShotGraph , TRUE ) ;
					}
				}
			}
		}

		// 自機の弾と敵、UFOとの当たり判定
		{
			// 弾が存在している場合のみ次の処理に映る
			if( ShotFlag == 1 )
			{
				for( i = 0; i < X; i++ ) {
					for( j = 0; j < Y; j++ ) {
						// 敵の生存状態を現す変数が1なら当たり判定
						if( EnemyAlive[i][j] == 1 )
						{
							// 敵との当たり判定
							if( ( ( ShotX > EnemyX[i][j] && ShotX < EnemyX[i][j] + EnemyW ) ||
								( EnemyX[i][j] > ShotX && EnemyX[i][j] < ShotX + ShotW ) ) &&
								( ( ShotY > EnemyY[i][j] && ShotY < EnemyY[i][j] + EnemyH ) ||
								( EnemyY[i][j] > ShotY && EnemyY[i][j] < ShotY + ShotH ) ) )
							{
								// 接触している場合は当たった弾の存在を消す
								ShotFlag = 0 ;

								// 敵の生存状態を表す変数に0を代入(死亡)
								EnemyAlive[i][j] = 0 ;

								// 敵の数を保持している変数を1減らす
								EnemyCount-- ;

								// スコアを増加させる
								Score += 10 ;

								// 弾が消えたのでループから抜ける
								break ;
							}
						}
					}
				}

				// UFOとの当たり判定(UFOが存在している場合のみ)
				if( ( ( ShotX > UfoX && ShotX < UfoX + UfoW ) ||
					( UfoX > ShotX && UfoX < ShotX + ShotW ) ) &&
					( ( ShotY > UfoY && ShotY < UfoY + UfoH ) ||
					( UfoY > ShotY && UfoY < ShotY + ShotH ) ) 
						&& UfoFlag == 1 )
				{
					// 接触している場合は当たった弾の存在を消す
					ShotFlag = 0 ;

					// UFOが存在しているかを保持する変数に「存在していない」を表す0を代入
					UfoFlag = 0 ;

					// プレイヤーがUFOを殺したことを保持する変数に90を代入
					UfoKilled = 90 ;

					// スコアを増加させる
					Score += 100 ;
				}
			}
		}

		// 敵の数を保持する変数が0の場合、敵の座標を元に戻して全員復活させる
		if( EnemyCount == 0 )
		{
			// 敵の数を保持する変数を元に戻す
			EnemyCount = X * Y ;

			// 全ての敵の座標を元に戻し、生存状態を表す全ての変数に1を代入
			for( i = 0; i < X; i++ )
			{
				for( j = 0; j < Y; j++ )
				{
					EnemyX[i][j] = 16 + i*32 ; 
					EnemyY[i][j] = 48 + j*32 ;
					EnemyAlive[i][j] = 1;
				}
			}

			// クリアした数を保持する変数を増加
			ClearCount++ ;
		}

		// ゲームオーバーになっているかを確認する処理
		for( i = 0; i < X; i++ )
		{
			for( j = 0; j < Y; j++ )
			{
				// 敵の弾が無敵状態でない時に自機に当たった場合
				if( ( ( ( PlayerX > EnemyShotX[i][j] && PlayerX < EnemyShotX[i][j] + EnemyShotW ) ||
					( EnemyShotX[i][j] > PlayerX && EnemyShotX[i][j] < PlayerX + PlayerW ) ) &&
					( ( PlayerY > EnemyShotY[i][j] && PlayerY < EnemyShotY[i][j] + EnemyShotH ) ||
					( EnemyShotY[i][j] > PlayerY && EnemyShotY[i][j] < PlayerY + PlayerH ) ) ) 
						&&	PlayerMuteki <= 0 )
				{
					// プレイヤーが死んだ時の画像を描画し、表画面に反映させる
					DrawGraph( PlayerX , PlayerY , PlayerGraph[2] , TRUE ) ;
					ScreenFlip() ;

					// 2秒ほど停止
					WaitTimer( 2000 );

					// 残機数を保持する変数を1減らし、プレイヤーの座標を初期化する
					PlayerCount-- ;
					PlayerX = 248 ; PlayerY = 464 ;

					// しばらくプレイヤーを無敵状態にする
					PlayerMuteki = 120;
				}

				// 敵が1体でも一定の領域を超えるか、残機数が0で敵の弾が自機に当たった場合
				if(	EnemyY[i][j] >= 480-16 || PlayerCount < 0 )
				{
					// 画面中央に、文字列を描画
					DrawString( 320-96 , 226 , "~GAME OVER~" , ColorWhite );

					// ゲームオーバー状態を保持する変数に1を代入
					GameOverFlag = 1;
				}
			}
		}
		
		// 裏画面の内容を表画面にコピーする
		ScreenFlip() ;

		// ゲームオーバーになった場合の処理
		if( GameOverFlag == 1 )
		{
				// しばらく表示させたままゲームを停止させる
				WaitTimer( 2000 );

				// ループから脱出する(タイトル画面へ)
				break;
		}

		// Windows 特有の面倒な処理をDXライブラリにやらせる
		// -1 が返ってきたらループを抜ける
		if( ProcessMessage() < 0 ) break ;

		// もしESCキーが押されていたらループから抜ける
		if( CheckHitKey( KEY_INPUT_ESCAPE ) ) break ;
	}

	return;				// ゲームの終了 
}


// 数値Numをn桁までグラフィック表示する関数(x, yで座標指定)
void NumberDraw( int Num, int n, int x, int y )
{
	int i , BeamWidth , g ;

	// Numが十進数で何桁になるか調べる
	BeamWidth = 0 ;
	for( i = 10 ; Num >= i ; i *= 10 ) BeamWidth ++ ;

	// 画面左上にグラフィックで描画
	// g は数字グラフィックを描く矩形の左端の座標
	g = (n - 1) * 16 + x ;	
	for( i = 0 ; i < n ; i ++ )
	{
		// 数字の描画(透過色あり)
		DrawGraph( g , y , NumberGraph[ Num % 10 ], TRUE ) ;

		// 描画X座標を移動
		g -= 16 ;

		// 1番下の桁が描画し終わったので一桁下げる
		Num /= 10 ;
	}
}
 そして、これより下が、タイトル画面を処理する方のプログラムです。

コード:


// メニュ-処理基本
#include "DxLib.h"
#include "Game.h"		// Gameモジュールの関数を使えるようにする

int SPoint ;			// 選択カーソルの位置
int PushReturn = 0 ;	// エンターキーが押しっぱなしでないか監視する変数

// 各処理の関数
void Control( void ) ;		// ゲームの操作方法を表示する関数
void End( void ) ;			// 何もしない関数

// 処理ポインタ配列
void ( *Method[] )( void ) =
{
	Game , Control , End
} ;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
						 LPSTR lpCmdLine, int nCmdShow )
{
	int i, SenntakuNum, PushCursor, TitleGraph;

	// 選択項目の文字列
	char *String[] =
	{
		"ゲームスタート" ,
		"操作方法" ,
		"終了",
		NULL
	} ;

	// 画面モードの設定
	SetGraphMode( 640 , 480 , 16 );

	// ウインドウモードに変更
	ChangeWindowMode( TRUE );

	// DXライブラリ初期化処理
	if( DxLib_Init() == -1 ) return -1;

	// グラフィックの描画先を裏画面にセット
	SetDrawScreen( DX_SCREEN_BACK ) ;

	// 選択ポインタの位置初期化
	SPoint = 0 ;

	// 選択項目の数を取得
	SenntakuNum = 3 ;

	// 押しっぱなしかどうかを保持する変数を初期化
	PushCursor = 0;

	// タイトルのグラフィックをメモリにロード
	TitleGraph = LoadGraph( "Graphic\\Title.jpg" ) ;

	// ループ
	while( ProcessMessage() == 0 )
	{
		// 画面を初期化(真っ黒にする)
		ClearDrawScreen();

		// タイトル画像描画
		DrawGraph( 32 , 96 , TitleGraph , TRUE ) ;

		// カーソル描画
		DrawBox( 320 - 64 , 320+16+SPoint * 32 , 320 - 48 , 320+16+SPoint * 32 - 16 , 
				GetColor( 255 , 255 , 0 ) , TRUE ) ;

		// 項目描画
		for( i = 0; String[i] != NULL; i++ )
		{
			DrawString( 320 - 32 , 320 + i * 32 , String[i] , GetColor( 255 , 255 , 255 ) ) ;
		}

		// キー入力
		{
			// カーソル移動(押しっぱなしなら移動しない)
			if( CheckHitKey( KEY_INPUT_UP ) != 0 && SPoint != 0 && PushCursor == 0 )
			{
				SPoint -- ;
				PushCursor = 1 ;		// 押しっぱなしかどうかを保持する変数に1を代入
			}
			if( CheckHitKey( KEY_INPUT_DOWN ) != 0 && SPoint < SenntakuNum - 1 && PushCursor == 0 ) 
			{
				SPoint ++ ;
				PushCursor = 1 ;		// 押しっぱなしかどうかを保持する変数に1を代入
			}

			// もし押しっぱなしでないなら、変数に0を代入
			if( CheckHitKey( KEY_INPUT_UP ) == 0 && CheckHitKey( KEY_INPUT_DOWN ) == 0 ) PushCursor = 0;

			// 決定キー時処理
			if( CheckHitKey( KEY_INPUT_RETURN ) != 0 && PushReturn == 0 )
			{
				// Enterキーの押下状態を保持する変数に1を代入
				PushReturn = 1;

				// 項目に応じた処理を行う
				Method[ SPoint ]() ;
			}

			// エンターキーが押しっぱなしでないならPushReturnに0を代入
			if( CheckHitKey( KEY_INPUT_RETURN ) == 0 ) PushReturn = 0;
		}

		// 裏画面の内容を表画面にコピーする
		ScreenFlip() ;

		// Endの項目で決定キーが押されたら終了
		if( CheckHitKey( KEY_INPUT_RETURN ) != 0 && SPoint == 2 ) break;

		// もしESCキーが押されていたらループから抜ける
		if( CheckHitKey( KEY_INPUT_ESCAPE ) ) break ;
	}

	DxLib_End() ;				// DXライブラリ使用の終了処理

	return 0 ;					// ソフトの終了
}


// 操作方法を表示する関数
void Control( void )
{
	int i;

	// 操作方法の文字列
	char *String[] =
	{
		"SPACE:弾を撃つ" ,
		"←→:移動" ,
		"Esc:ゲーム終了",
		NULL
	} ;

	// ループ
	while( ProcessMessage() == 0 )
	{
		// 画面を初期化(真っ黒にする)
		ClearDrawScreen();

		// 操作方法を説明する
		for( i = 0; String[i] != NULL; i++ )
		{
			DrawString( 320 - 32 , 320 + i * 32 , String[i] , GetColor( 255 , 255 , 255 ) ) ;
		}

		// 裏画面の内容を表画面にコピーする
		ScreenFlip() ;

		// キー入力
		{
			// ENTERキーが押されていたらループから抜ける
			if( CheckHitKey( KEY_INPUT_RETURN ) && PushReturn == 0 )
			{
				// ENTERキーの押下状態を保持する変数に1を代入
				PushReturn = 1;

				break ;
			}
			
			// ENTERキーが押されてなかったら押下状態を保持する変数に0を代入
			if( CheckHitKey( KEY_INPUT_RETURN ) == 0 )	PushReturn = 0;
		}

		// ESCキーが押されていたらループから抜ける
		if( CheckHitKey( KEY_INPUT_ESCAPE ) ) break ;
	}
}

// 何もしない関数
void End( void )
{
	return;
}

 ゲームを処理する方のプログラムで、145行目~158行目あたりでスコアを表示することができました。しかし、ハイスコアの方だと手詰まりです。

 タイトル画面の方で、Game()の引数にハイスコアを格納する変数を渡してあげて、ゲーム内でif文でスコアより大きかったらハイスコアにスコアを代入して、ゲームをする画面の方からタイトルに戻る時に、返り値をハイスコアにしてあげればタイトル画面に表示できると思ったのですが・・・

 タイトル画面の方は、処理ポインタ配列を選んでやることになってしまって、返り値を変数に代入することができません。

 どうすれば、ハイスコアをタイトル画面とゲーム画面の両方に表示することができるでしょうか。

けんじん

Re: ハイスコアの表示方法について

#2

投稿記事 by けんじん » 14年前

すみません、今のCの知識と、OS等を書き忘れていました。

使っているのは、

WindowsVista、Visual Studio 2008、DXライブラリです。

Cの知識としては、for文、if文などはそれなりに使い方はわかりますが、ポインタや、メモリの動的確保などがまだあまりできてない状況です。

hss12

Re: ハイスコアの表示方法について

#3

投稿記事 by hss12 » 14年前

単純にハイスコアのグローバル変数を作って
超えたら代入でどうでしょうか。

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

Re: ハイスコアの表示方法について

#4

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

>タイトル画面の方は、処理ポインタ配列を選んでやることになってしまって、返り値を変数に代入することができません。

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

けんじん

Re: ハイスコアの表示方法について

#5

投稿記事 by けんじん » 14年前

hss12さん、伝説なるハッカーさん、返信ありがとうございます。
hss12 さんが書きました:単純にハイスコアのグローバル変数を作って超えたら代入でどうでしょうか。
 どうしても、タイトル画面の方で「定義されてない識別子です」って出たんですが、なんとかできました。
 extern指定子を使えば、「宣言が他の場所にも書かれている」ことをコンパイラに知らせることができるんですね。初めて知りました。
 externを使ってハイスコアを格納するグローバル変数を作ったら、タイトルでも宣言できたことになってました。
伝説なるハッカー さんが書きました:switch~caseではダメなのですか?
 switch~caseでやったらできました。DXライブラリのメニュー処理の基本のプログラムを見て、これじゃないといけないって決めつけてたみたいです。


 質問からずれてしまうんですが、どっちでやった方がいいんでしょうか。
 龍神録さんのとこだと、グローバル変数は他のファイルで参照しちゃ駄目だと言ってますし、かといって関数の戻り値だと、1つの値しか返せないし・・・
 やっぱりその場その場で臨機応変でやればいいんでしょうか?

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

Re: ハイスコアの表示方法について

#6

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

どっちをやれば正解と言うわけではないですが、プロの視点からすれば無闇にグローバル変数を使うのは考えものです。
あと戻り値が1つしか返せないのは構造体を使えば出来ます。

ソースコード自体の課題点は、
(1)ローカル変数だけで無くファイルスコープの変数を適材適所で使えるようにする。
(2)構造体で変数をグループ分けする。
(3)Game()関数に機能を盛り込みすぎているので、もっと細かく関数分けする。
(4)構造体のポインタによる引数渡しなどのテクニックを活用。
(5)メインループが多重構造をしているのはバグの元なので止める。1つのループが基本でWinMainに集中させる。
メニュー⇒ゲーム本編の切り替えは状態遷移を使う。
「C言語~ゲームプログラミングの館~ 34. メイン関数の書き方。」
http://dixq.net/g/37.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

けんじん

Re: ハイスコアの表示方法について

#7

投稿記事 by けんじん » 14年前

なるほど!!!すごく参考になりました。

ありがとうございます。ソースコード自体も、関数分けとか多重構造しないように頑張ってみます!

閉鎖

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