トップページ > 記事閲覧
STG自機の当たり判定
名前:DX初心者 日時: 2009/12/31 15:36

現在DXライブラリを使ってSTGを作ろうとしてる者です。
敵の当たり判定を作った後に自機の当たり判定を作ろうとしてるのですが、どうしても上手く出来ずここに書き込みました。
ソース汚いですが、宜しくお願いします。

#include "DxLib.h"

#define SHOT 20
#define MSHOT 20
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine, int nCmdShow )
{
	int jikiX , jikiY , jikiGraph , tekiX , tekiY , tekiW , tekiH , tekiMuki ,
		tekiGraph , ShotX[SHOT] , ShotY[SHOT] , ShotH , ShotW , ShotFlag[SHOT] ,
		ShotGraph , ShotBFlag , i , j , tekiDamageFlag , tekiDamageCounter , tekiDamageGraph ,
		ETamaX[MSHOT] , ETamaY[MSHOT] , ETamaFlag[MSHOT] ,ETamaW , ETamaH , ETamaGraph , ETamaCounter ,
		jikiDamageFlag , jikiDamageCounter , jikiDamageGraph ,jikiH , jikiW ;


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

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

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

	//自機のグラフィックをメモリにロード&表示座標をセット
	jikiGraph = LoadGraph( "reimu1.PNG" ) ;
	jikiX = 288 ; jikiY = 400 ;
	jikiDamageGraph = LoadGraph( "dame.bmp" ) ;
	jikiDamageFlag = 0 ;

	//自機のグラフックサイズを得る
	GetGraphSize( jikiGraph , &jikiW , &jikiH ) ;

	// 自機の弾のグラフィックをメモリにロード
	ShotGraph = LoadGraph( "tama2.bmp" ) ;

	for( i = 0 ; i < SHOT ; i ++ )
	{
		ShotFlag[i] = 0 ;
	}
	// 自機の弾のグラフィックのサイズをえる
	GetGraphSize( ShotGraph , &ShotW , &ShotH ) ;


	// 敵のグラフィックをメモリにロード&表示座標をセット
	tekiGraph = LoadGraph( "youmu1.bmp" ) ;
	tekiX = 0 ; tekiY = 50 ;
	tekiDamageGraph = LoadGraph( "dame.bmp" ) ;
	tekiDamageFlag = 0 ;

	// 敵のグラフィックのサイズを得る
	GetGraphSize( tekiGraph , &tekiW , &tekiH ) ;

	// 敵の弾のグラフィックをロード
	ETamaGraph = LoadGraph( "tama4.bmp" ) ;
	for( j = 0 ; j < MSHOT ; j ++ )
	{
		ETamaFlag[j] = 0 ;
	}

	// 敵の弾のグラフィックのサイズを得る
	GetGraphSize( ETamaGraph , &ETamaW , &ETamaH ) ;

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

	// ショットボタンが前のフレームで押されたかどうかを保存する変数に0(押されいない)を代入
	ShotBFlag = 0 ;

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

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

		// 自機の操作ルーチン
		{
			if( CheckHitKey( KEY_INPUT_UP ) == 1 ) jikiY -= 3 ;
			if( CheckHitKey( KEY_INPUT_DOWN ) == 1 ) jikiY += 3 ;
			if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ) jikiX -= 3 ;
			if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) jikiX += 3 ;

			// スペースキーを押していて、且弾が撃ち出されていなかったら弾を発射する
			if( CheckHitKey( KEY_INPUT_SPACE ))
			{
				if( ShotBFlag ==0 )
				{
					for(i = 0 ; i< SHOT ; i ++)
					{
						if( ShotFlag[i] ==0)
						{
				int Bw, Bh, Sw, Sh ;

				// 自機と弾の画像のサイズを得る
				GetGraphSize( jikiGraph , &Bw , &Bh ) ;
				GetGraphSize( ShotGraph , &Sw , &Sh ) ;

				// 弾の位置をセット、位置は自機の中心にする
				ShotX[i] = ( Bw - Sw ) / 2 + jikiX ;
				ShotY[i] = ( Bh - Sh ) -16 + jikiY ;

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

				break ;
			}
		}
	}
			ShotBFlag = 1;
		}
			else
			{
				ShotBFlag = 0;
			}
			// 自機が画面出そうになっていたら画面内の座標に戻してあげる
			if( jikiX < 0 ) jikiX = 0 ;
			if( jikiX > 670 - 64 ) jikiX = 670 - 64  ;
			if( jikiY < 0 ) jikiY = 0 ;
			if( jikiY > 510 - 64 ) jikiY = 510 - 64 ;

			// 自機を描画
			DrawGraph( jikiX , jikiY , jikiGraph , TRUE ) ;
		}
	for( i=0 ; i < SHOT ; i++ )
	{

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

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

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

			if( jikiDamageFlag == 1 )
			{
				// ダメージ時のグラフィックを描画する
				DrawGraph( jikiX , jikiY , jikiDamageGraph , TRUE ) ;

				jikiDamageCounter ++ ;

				// ダメを食らったら下のフレーム数分描画をかえる
				// 元に戻してあげる
				if( jikiDamageCounter == 10 )
				{
					jikiDamageFlag = 0 ;
				}
			}
			else
			{

			for( j = 0 ; j < MSHOT ; j ++ )
			{
				if( ETamaFlag[ j ] == 1 )
				{
					//当たり判定
					if( ( ( ETamaX[j] > jikiX && ETamaX[j] < jikiX + jikiW ) ||
						( jikiX > ETamaX[j] && jikiX < ETamaX[j] + ETamaW ) ) &&
						( ( ETamaY[j] > jikiY && ETamaY[j] < jikiY + jikiH ) ||
						( jikiY > ETamaY[j] && jikiY < ETamaY[j] + ETamaH ) ) )
					{
						// 接触している場合は当たった弾の存在を消す
						ETamaFlag[ j ] = 0 ;
						jikiDamageFlag = 1 ;
						jikiDamageCounter = 0 ;
					}
				}
			}
		}
	}

			

		// 敵の移動ルーチン
		{
			if( tekiDamageFlag == 1 )
			{
				// ダメージ時(敵)のグラフィックを描画する
				DrawGraph( tekiX , tekiY , tekiDamageGraph , TRUE ) ;

				tekiDamageCounter ++ ;

				// ダメを食らったら下のフレーム数分描画をかえる
				// 元に戻してあげる
				if( tekiDamageCounter == 1 )
				{
					tekiDamageFlag = 0 ;
				}
			}
			else
			{

			// 敵の座標を移動している方向に移動する
			if( tekiMuki == 1 ) tekiX += 3 ;
			if( tekiMuki == 0 ) tekiX -= 3 ;

			// 敵が画面でそうになっていたら画面内の座標に戻してあげ、移動する方向も反転する
			if( tekiX > 576 )
			{
				tekiX = 576 ;
				tekiMuki = 0 ;
			}
			//↑の反対側処理
			if( tekiX < 0 )
			{
				tekiX = 0 ;
				tekiMuki = 1 ;
			}

			// 敵を描画
			DrawGraph( tekiX , tekiY , tekiGraph , TRUE ) ;

			//敵の弾の処理
			ETamaCounter ++ ;
			 if( ETamaCounter == 1 )
			 {
				 if( ETamaFlag[j] == 0 )
				 {
						ETamaX[j] = tekiX + tekiW / 2 - ETamaW / 2;
						ETamaY[j] = tekiY + tekiH +6 - ETamaH / 2;

						ETamaFlag[j] = 1 ;
				 }
				 ETamaCounter = 0 ;
			 }

			}
		}

		//敵の弾の状態が飛んでる時のみ弾の移動処理
		if( ETamaFlag[j] == 1 )
		{
			ETamaY[j] += 10 ;
			
			if( ETamaY[j] > 510 ) ETamaFlag[j] = 0 ;
			DrawGraph( ETamaX[j] , ETamaY[j] , ETamaGraph , TRUE ) ;

			}


			// 弾と敵の当たり判定、弾の数だけ繰り返す
			for( i = 0 ; i < SHOT ; i ++ )
			{
				// 弾iが存在している場合のみ次の処理に映る
				if( ShotFlag[ i ] == 1 )
				{
					//敵との当たり判定
					if( ( ( ShotX[i] > tekiX && ShotX[i] < tekiX + tekiW ) ||
						( tekiX > ShotX[i] && tekiX < ShotX[i] + ShotW ) ) &&
						( ( ShotY[i] > tekiY && ShotY[i] < tekiY + tekiH ) ||
						( tekiY > ShotY[i] && tekiY < ShotY[i] + ShotH ) ) )
					{
						// 接触している場合は当たった弾の存在を消す
						ShotFlag[ i ] = 0 ;
						tekiDamageFlag = 1 ;
						tekiDamageCounter = 0 ;
					}
				}
			}
}


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


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

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

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

	return 0 ;					// ソフトの終了
}
メンテ

Page: 1 |

Re: STG自機の当たり判定 ( No.1 )
名前:いっち 日時:2009/12/31 17:29

ソースを拝見させて頂きました。
128行目あたりのfor文
> for( i=0 ; i < SHOT ; i++ )
これはおそらく自機の弾の移動や当たり判定を行うためのループだと思いますが、
その中に敵の移動ルーチンや弾の発射ルーチンまで入っているのがそもそもの問題点だと思われます。
if文やfor文のブロック構造の対応が捉えきれていないように見受けられますので、
1つ1つ確認を取りつつコーディングすることをお勧めします。
メンテ
Re: STG自機の当たり判定 ( No.2 )
名前:いっち 日時:2009/12/31 18:38

ソースを修正してみました。
基本的には適切なループを与えて切り貼りしただけです。
敵が大量の弾を打ち出しますが、これは仕様でMSHOTの数だけ連射します。
修正した場所は//-- コメント --の形でコメントを入れてあります。

ttp://gigabyteserver.com/uploader01/upload.php?counting=918&firen=winplus.jp918.zip
メンテ
Re: STG自機の当たり判定 ( No.3 )
名前:DX初心者 日時:2009/12/31 20:53

いっち様
ソースまで直して頂いて有難う御座います。
大変助かりました、また解らない事がありましたら
ここをご利用させて頂くと思うので、今後もよろしくお願いします。
メンテ
Re: 追記 ( No.4 )
名前:DX初心者 日時:2009/12/31 20:59

いっち様
//の部分のアドバイス大変解り易く助かりました
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存