ステージの切り替え

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

ステージの切り替え

#1

投稿記事 by sina » 13年前

現在、visualStudio2010を使い全10ステージのブロック崩しをDxLibで作っているのですが
ステージの切り替えをどのように書けばいいのか分からず止まっています
本格的にゲームプログラミングを勉強し始めたのは2週間ほど前です。

コード:

/*block kowasi.c*/
#include<DxLib.h>
#include<math.h>
#include<stdio.h>
#define WALL_NUM 100

enum {
    STATE_TITLE,    //タイトル
    STATE_MAIN,     //メイン
	STATE_END     //ゲームの終了
};

// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPSTR lpCmdLine, int nCmdShow )
{

 // ウインドウモードに変更
 ChangeWindowMode( TRUE ) ;
 SetGraphMode( 640, 480, 32 ) ;

 // DXライブラリ初期化
 if( DxLib_Init() == -1 )
  {
	 return 0;
  }
 // 描画先を裏画面にする
 SetDrawScreen( DX_SCREEN_BACK ) ;
 int i=0;//ループ用
 int stage=0;//ステージ


 /*******************バー関係***************************/

 //バーの設定
 int BarGHandle ; //グラフィックハンドル
 int BarGSizeX ; //画像のサイズ(よこ)
 int BarGSizeY ; //画像のサイズ(たて)
 int BarX = 150 ; //バーの初期X座標
 int BarY = 400 ; //バーの初期Y座標
 int BarVX = 10 ; //X座標の速度
 int BarVY = 10 ; //Y座標の速度
 int BarHitFlag ; //ぶつかったか

 double BarCenterX ; //バーの中心X
 double BarCenterY ; //バーの中心Y

// PNG画像のメモリへの読みこみ(バー)
 BarGHandle = LoadGraph( "板.bmp" ) ;
// 読みこんだグラフィックのサイズを得る(バー)
 GetGraphSize( BarGHandle , &BarGSizeX , &BarGSizeY );


/*********************ボール関係********************************/
  
// ボール画像の読みこみ
 int BallGHandle = LoadGraph( "ball.bmp" );
// ボールとブロックの初期位置の座標を設定する
 int BallX = 100 ; //ボールのX座標
 int BallY = 50 ; //ボールのY座標

 double BallCenterX ; //ボールの中心X座標
 double BallCenterY ; //ボールの中心Y座標

 int BallVX = 8 ; //X座標の速度
 int BallVY = 5 ; //Y座標の速度

 int BallStopFlag = 1 ; //ボールが止まっているかどうか


/****************ブロック関係***************************/
 int j=0;//ブロックの個数
 int WallX[WALL_NUM];
 int WallY[WALL_NUM];

 int WallHP[WALL_NUM]={0};
 int WallHitFlag[WALL_NUM] = {0} ; //ぶつかったかどうか
 int WallType[WALL_NUM];

 double WallCenterX ; //ブロックの中心X座標
 double WallCenterY ; //ブロックの中心Y座標

 int WallHPSum ; //ブロックの残りHP(総和)

 // 読みこんだグラフィックのサイズを得る
 int BallGSizeX ; //画像のサイズ(よこ) 
 int BallGSizeY ; //画像のサイズ(たて)
 GetGraphSize( BallGHandle , &BallGSizeX , &BallGSizeY);

 // 画像の読みこみ(ブロック)
 int WallGHandle[WALL_NUM];

// 読みこんだグラフィックのサイズを得る(ブロック)
 int WallGSizeX[WALL_NUM] ; //ブロック画像のサイズ(よこ) 
 int WallGSizeY[WALL_NUM] ; //ブロック画像のサイズ(たて) 
 
 //***********************スコア関連**************************//
 int MissCounter = 0 ; //ミスした回数
 int GameOverFlag = 0 ; //ゲームオーバー
 int GameClearFlag = 0; //ゲームクリア



 //**************************ファイル読み込み***********************************//
 FILE *fp ; //ファイル構造体のポインタ
 char str[256] ; //読み込んでる文字を入れておく
 char c ; //読み込んだ文字
 int block_num = 0 ; //何個目のブロック
 int para_num = 0 ; //何個目のパラメーターか


 // ファイル名
 char *filename[64]={"stage_block1.csv"};
 switch(stage)
		{
			case 0:   filename[64] ="stage_block1.csv";
			case 1:   filename[64] ="stage_block2.csv";
			case 2:   filename[64] ="stage_block3.csv";
			case 3:   filename[64] ="stage_block4.csv";
			case 4:   filename[64] ="stage_block5.csv";
			case 5:   filename[64] ="stage_block6.csv";
			case 6:   filename[64] ="stage_block7.csv";
			case 7:   filename[64] ="stage_block8.csv";
			case 8:   filename[64] ="stage_block9.csv";
			case 9:   filename[64] ="stage_block10.csv";
		}
		
 // ファイルを読み込む
 fp=fopen(*filename, "r");
 // 一行目を取得(この部分は説明とかが書いてあって使わない)
 fgets( str , sizeof( str ) , fp );
 printfDx( "%s" , str ); // 簡易表示
 ScreenFlip();
 WaitTimer(200);

// パラメーターを抜き出す
 while( 1 )
 {
	for( i = 0 ; i < sizeof( str ) ; i++ )
	{
		// 一文字取得する
		c = fgetc( fp );
		str[i] = c ;
		// もしその一文字が改行コードやコンマだったら
		if( c == '\n' || c == ',' )
		{
			// そこで区切る(strにはそれまでの文字列が入ってる)
			str[i] = '\0' ;
			break;
		}
		// もしファイルの終わりだったら
		if( c == EOF )
		{
			// for文を抜ける
			break;
		}
	}
	// もしファイルの終わりだったら
	if( c == EOF )
	{
		// while文を抜ける
		break;
	}

	// 取得したパラメータを取り込む
	switch( para_num )
	{
		case 0: WallX[block_num] = atoi( str );break;
		case 1: WallY[block_num] = atoi( str );break;
		case 2: WallType[block_num] = atoi( str );break;
	}
	// ブロックの読み込み
	char blocks[16] = { "block" } ;
	for(i = 0 ; i<WALL_NUM; i++ )
	{
		switch( WallType[i])
		{
			case 0: break;
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
			// 文字1~9は49~57なので無理やり合わせる
			blocks[5] = (char)( WallType[i] + 48 );
			blocks[6] = '.' ;
			blocks[7] = 'b' ;
			blocks[8] = 'm' ;
			blocks[9] = 'p' ;
			blocks[10] = '\0';
			WallGHandle[i] = LoadGraph( blocks ) ;
			// 読みこんだグラフィックのサイズを得る
			GetGraphSize( WallGHandle[i] , &WallGSizeX[i] , &WallGSizeY[i] ) ;
			// WallHPを設定
			WallHP[i] = 3 ;
		}
	}
//**************************デバッグ用***************************//
		printfDx( "(BlockNumber:%d,ParameterNumber:%d) = %s,\n" , block_num , para_num , str );
		ScreenFlip();
		WaitTimer(200);
		// 次のパラメータに移る
		para_num++;
		// もうそのブロックのパラメーターを取り込み終わったなら
		if( para_num ==3 )
		{
			// 次のブロックに移って続きをする
			para_num = 0;
			block_num++;
		}
		j++;
 }
		// ファイルを閉じる
		fclose( fp ) ;


/////////////////////////////////メインループ///////////////////////////////////////////////////////

 while( ProcessMessage() == 0)
{

	ClearDrawScreen() ;
	// バー
	DrawGraph( BarX , BarY , BarGHandle , TRUE ) ;
	// ボール
	DrawGraph( BallX , BallY , BallGHandle , TRUE);
	//ボールと枠の衝突判定(速度にマイナス1をかけることで向きを逆にする)
	//この場合ボールはX座標100~500,Y座標50~400の範囲を移動することになります。
	if( BallX + BallGSizeX >= 640 )
	{
		BallVX *= -1 ; //BallXは左端のX座標なので、右端のX座標はボール画像の幅の値を加える
		PlaySoundFile( "shot.wav" ,DX_PLAYTYPE_BACK ) ;
	}
	if( BallX <= BallGSizeX )
	{
		BallVX *= -1 ;
		PlaySoundFile( "shot.wav" ,DX_PLAYTYPE_BACK ) ;
	}
	if( BallY + BallGSizeY >= 500 )
	{
		BallVY *= -1 ; //BallYは上端のY座標なので、下端のY座標はボール画像の高さの値を加える
		PlaySoundFile( "shot.wav" ,DX_PLAYTYPE_BACK ) ;
	}
	if( BallY <= BallGSizeY )
	{
		BallVY *= -1 ;
		PlaySoundFile( "shot.wav" ,DX_PLAYTYPE_BACK ) ;
	}

	if( !BallStopFlag )
	{ 
		//ボールが止まってなかったら
		BallX += BallVX ; //X方向の速度を足す
		BallY += BallVY ; //Y方向の速度を足す
	} 
	else
	{ 
		//止まってたら
		BallX = ( BarX * 2 + BarGSizeX - BallGSizeX)/2;//バーの中心にくっつける
		BallY = BarY - BallGSizeY ;
	}

	if( ( ( BallY - BallVY + BallGSizeY <= 450 ) && ( BallY + BallGSizeY >=450 ) ) || ( BallY + BallGSizeY >=450 ) )
	{
		MissCounter++ ;//ミス回数を1増やす
		BallStopFlag = TRUE ;//ボールを一度止める
		BallX =(BarX*2+BarGSizeX-BallGSizeX )/2; //バーの中心に乗っける
		BallY = BarY - BallGSizeY ;
	}

/////****************あたり判定******************************//////////////////	
for( i = 0 ; i <(j/3) ; i++ )
{	
	if(WallHP[i]>0)
	{
		//ボールとブロックとの衝突判定
		BallCenterX = BallX + BallGSizeX / 2 ; //ボールの中心X座標を計算する
		BallCenterY = BallY + BallGSizeY / 2 ; //ボールの中心Y座標を計算する
		WallCenterX = WallX[i] + WallGSizeX[i]/2; //ブロックの中心X座標を計算する
		WallCenterY = WallY[i] + WallGSizeY[i]/2; //ブロックの中心Y座標を計算する

		if( abs( BallCenterX - WallCenterX ) <= ( BallGSizeX + WallGSizeX[i] ) / 2 )
		{
			//下からぶつかる時
			if( ( BallY-BallVY+BallGSizeY > WallY[i] + WallGSizeY[i]) && ( BallY<WallY[i] + WallGSizeY[i]) )
			{
				 BallVY *= -1 ;
				 BallY = ( WallY[i] + WallGSizeY[i] ) * 2 - BallY ;
				 WallHitFlag[i] = TRUE;//あたり判定
			 }
			//上からぶつかる時
			 if( ( BallY - BallVY + BallGSizeY <= WallY[i] ) && ( BallY + BallGSizeY >= WallY[i] ) )
			 {
				 BallVY *= -1 ;
				 BallY = ( WallY[i] - BallGSizeY ) * 2 - BallY ;
				 WallHitFlag[i] = TRUE;
			 }
			
		 }
	
		//ボールとブロックが横に並ぶ(重なる)とき
		if( abs( BallCenterY - WallCenterY) <= ( BallGSizeY + WallGSizeY[i] ) / 2 )
		{
			//左からぶつかる時
			if( ( BallX - BallVX >= WallX[i] + WallGSizeX[i] ) && ( BallX <= WallX[i] + WallGSizeX[i] ) )
			 {
				BallVX *= -1 ;
				BallX = ( WallX[i] + WallGSizeX[i] ) * 2 - BallX;
				WallHitFlag[i] = TRUE;

			 }
			//右からぶつかる時
			if( ( BallX - BallVX + BallGSizeX <= WallX[i] ) && ( BallX + BallGSizeX >= WallX[i] ) )
			 {
				BallVX *= -1 ;
				BallX = ( WallX[i] - BallGSizeX ) * 2 - BallX;
				WallHitFlag[i] = TRUE;
			 }
		
		}
		if( WallHitFlag[i] == TRUE )
		{
			//HPを1減らす
			WallHP[i]-- ;
			WallHitFlag[i] = FALSE ;
		}
	}
}
clsDx() ; //簡易表示文章をクリアする
 for(i = 0 ; i<(j/3); i++ )
 {
	//HPが1以上なら 
	 if( WallHP[i] > 0 )
	 {
		DrawGraph( WallX[i] , WallY[i] , WallGHandle[i] , TRUE ) ;
	 }
 }

 //バーの移動(キー入力)
 // 左右のキー入力に対応して BarX, BarY の座標値を変更する
 if( CheckHitKey( KEY_INPUT_LEFT ) == 1 )
 {
	if( BarX - BarVX <=0)
	{
		BarX = 0 ;
	}
	else 
	{
		BarX -= BarVX ;
	}
 }
 if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 )
 {
	if( BarX + BarGSizeX + BarVX >=640) 
	{
		BarX=640-BarGSizeX ;
	}
	else 
	{
		BarX += BarVX ;
	}
 }

 //スペースキーでボールを動かし発射
 if((BallStopFlag) && ( CheckHitKey( KEY_INPUT_SPACE ) == 1 ) )
 {
	 BallStopFlag = FALSE;
 }

//ボールとバーの衝突判定

 BarCenterX = BarX + BarGSizeX / 2 ; 
 BarCenterY = BarY + BarGSizeY / 2 ; 

 if( abs( BallCenterX - BarCenterX ) <= ( BallGSizeX + BarGSizeX ) / 2 )
 {
	if( ( BallY - BallVY >= BarY + BarGSizeY ) && ( BallY <= BarY + BarGSizeY ) )
	{
		BallVY *= -1 ;
		BallY = BarY + BarGSizeY ;
		BarHitFlag = TRUE;
	}
	if( ( BallY - BallVY + BallGSizeY <= BarY ) && ( BallY + BallGSizeY >= BarY ) )
	{
		BallVY *= -1 ;
		BallY = BarY - BallGSizeY ;
		BarHitFlag = TRUE;
	}
 }

 if( abs( BallCenterY - BarCenterY ) <= ( BallGSizeY + BarGSizeY ) / 2 )
 {
	if( ( BallX - BallVX >= BarX + BarGSizeX ) && ( BallX <= BarX + BarGSizeX ) )
	 {
		BallVX *= -1 ;
		BallX = BarX + BarGSizeX ;
		BarHitFlag = TRUE;
	 }
	if( ( BallX - BallVX + BallGSizeX <= BarX ) && ( BallX + BallGSizeX >= BarX ) )
	{
		BallVX *= -1 ;
		BallX = BarX - BallGSizeX ;
		BarHitFlag = TRUE;
	}
 }

 //ゲームオーバー判定
 if( MissCounter >= 10 )
 {
	GameOverFlag = TRUE ;
	BallVX = 0 ;
	BallVY = 0 ;
 }

//ゲームクリア判定
 WallHPSum = 0;
 for( int i = 0; i<(j/3);i++ )
 {
	WallHPSum += WallHP[i];
 }
 if( WallHPSum == 0 )
 {
	GameClearFlag = TRUE ;
	BallVX = 0 ;
	BallVY = 0 ;
 }

 printfDx( "BallX:%d\nBallY:%d\n" , BallX , BallY ) ;
 printfDx( "Miss:%d\n" , MissCounter ) ;
//ゲームオーバーだったらそのように表示
 if( GameOverFlag ) printfDx( "GAME OVER" ) ;
//ゲームクリアだったらそのように表示
 if( GameClearFlag )
 {
	printfDx( "GAME CLEAR" );
	stage++;
 }





// ボールを移動させる(=表示させる座標を変更する)
BallX += BallVX ; //ボールのX座標にX方向の速度を足す
BallY += BallVY ; //ボールのY座標にY方向の速度を足す
ScreenFlip() ;
WaitTimer( 20 ) ;

} // メインループここまで(ここまできたらメインループの始めに戻る)

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

 return 0 ;

}

かなりコードが読みにくいと思います、すいませんm( _ _ )m。


     ステージクリア
        ↓
      stage変数を1増やす

switchでのステージの再読み込み


 という感じで行おうと思っているのですが方法が思いつきませんでした。
 過去の質問も探してみたのですがどうも判りませんでした。
 よろしくお願いします。

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

Re: ステージの切り替え

#2

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

そうですね。
まず、インデントが乱れていますので整理が必要だと思います。
「mixcpp/投稿前チェックリスト - PukiWiki」
http://uchan.net/w/index.php?mixcpp%2F% ... 5%B9%A5%C8

でプログラムの中身ですが
「補足資料.11章 書いてはいけない4つの処理」
http://dixq.net/g/h_11.html
に該当していますので、ここを直さないとステージ分けが困難です。

それと色々と関数化をすることでプログラムを整理してステージ処理の共通化が行えます。
同じ処理を何度も書いているのはバグの元でしかありませんので直すことは必須だと思ってください。

まず、これを片づけないと複数のステージに分ける事が難しいです。

【補足】
その他にも表面化していませんがバグが散見されます。
filename[64] = "stage_block1.csv";
とか
WallGHandle = LoadGraph( blocks ) ;
で同じ画像を何度でも読んでいる気配があるとか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sina

Re: ステージの切り替え

#3

投稿記事 by sina » 13年前

まずは整理しなければダメという事ですね
自分なりにやってみます
ありがとうございました。

閉鎖

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