当たり判定

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
KSK
記事: 79
登録日時: 9年前

当たり判定

#1

投稿記事 by KSK » 9年前


KSKです。
早速質問をさせていただきます。
では、コードをのせます。

コード:

#include "DxLib.h"


#define SHOT 1
#define SUPER_SHOT 100
#define HIGHPER_SHOT 100
#define ENEMY 6



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

	int PlayerX , PlayerY , PlayerGraph ;
	int EnemyX[ENEMY] , EnemyY[ENEMY] , EnemyGraph , EnemyFlag[ENEMY] , EnemyClearCounter[ENEMY] ;
	int ShotX[SHOT] , ShotY[SHOT] , ShotFlag[SHOT] , ShotGraph , ShotSound , ShotSoundFlag ;
	int SuperShotX[SUPER_SHOT] , SuperShotY[SUPER_SHOT] , SuperShotFlag[SUPER_SHOT] , SuperShotGraph , SuperShotSound , SuperShotSoundFlag ;
	int HighperShotX[HIGHPER_SHOT] , HighperShotY[HIGHPER_SHOT] , HighperShotFlag[HIGHPER_SHOT] , HighperShotGraph ;
	int GreenGraph , BlueGraph ;
	int i ;
	int v ;
	int white ;
	int e ;
	int s ;
	int score ;
	int MessageBoxFlag ;

	
	SetWindowIconID( 101 ) ;
	SetMainWindowText( "ASHOOT" ) ;
	// 画面モードの設定
	SetGraphMode( 640 , 480 , 16 ) ;
	SetWindowStyleMode( 7 ) ;
	SetWindowSizeExtendRate( 1 ) ;

	MessageBoxFlag = MessageBox( NULL , TEXT( "WINDOW MODE?" ) , TEXT( "SCREEN MODE" ) , MB_YESNOCANCEL | MB_ICONQUESTION ) ;
	if( MessageBoxFlag == IDYES )
	{
		ChangeWindowMode( TRUE ) ;
	}
	if( MessageBoxFlag == IDCANCEL )
	{
		goto END ;
	}

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


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

	// 自機のグラフィックをメモリにロード&表示座標をセット
	PlayerGraph = LoadGraph( "red.bmp" ) ;
	PlayerX = 320 - 64 ; PlayerY = 480 - 128 ;

	//敵のグラフィックをメモリにロード&表示座標をセット
	EnemyGraph = LoadGraph( "enemy.bmp" ) ;
	EnemyX[0] = 288 ;
	EnemyX[1] = 138 ;
	EnemyX[2] = 416 ;
	EnemyX[3] = 138 ;
	EnemyX[4] = 288 ;
	EnemyX[5] = 416 ;
	
	// 弾のグラフィックをメモリにロード
	HighperShotGraph = LoadGraph( "bighighpershot.bmp" ) ;

	SuperShotGraph = LoadGraph( "supershot.bmp" ) ;

	ShotGraph = LoadGraph( "shot.bmp" ) ;

	ShotSound = LoadSoundMem( "shotsound.wav" ) ;
	ShotSoundFlag = 0 ;

	SuperShotSound = LoadSoundMem( "supershotsound.wav" ) ;
	SuperShotSoundFlag = 0 ;

	GreenGraph = LoadGraph( "green.bmp" ) ;

	BlueGraph = LoadGraph( "blue.bmp" ) ;

	white = GetColor( 255 , 255 , 255 ) ;

	score = 0 ;

	// 弾が画面上に存在しているか保持する変数に『存在していない』を意味する0を代入しておく
	for( v = 0 ; v < SHOT ; v++ )
	{
		ShotFlag[v] = 0 ; 
	}
	for( i = 0 ; i < SUPER_SHOT ; i ++ )
	{
		SuperShotFlag[i] = 0 ;
	}
	for( e = 0 ; e < ENEMY ; e ++ )
	{
		EnemyY[e] = 0 ;
		EnemyFlag[e] = 0 ;
		EnemyClearCounter[e] = 0 ;
	}

	EnemyFlag[0] = 1 ;


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

		DrawGraph( 0 , 0 , GreenGraph , FALSE ) ;
		DrawFormatString( 528 , 32 , white , "SCORE:%d" , score ) ;

		// 自機の操作ルーチン
		{
			// ↑キーを押していたら自機を上に移動させる
			if( CheckHitKey( KEY_INPUT_UP ) == 1 ) PlayerY -= 5 ;

			// ↓キーを押していたら自機を下に移動させる
			if( CheckHitKey( KEY_INPUT_DOWN ) == 1 ) PlayerY += 5 ;

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

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

			if( score >= 100 )
			{
			if( CheckHitKey( KEY_INPUT_X ) )
			{
				// 画面上にでていない弾があるか、弾の数だけ繰り返して調べる
				for( i = 0 ; i < SUPER_SHOT ; i ++ )
				{
					// 弾iが画面上にでていない場合はその弾を画面に出す
					if( SuperShotFlag[i] == 0 )
					{
						// 弾iの位置をセット、位置はボール君の中心にする
						SuperShotX[i] = PlayerX + 48 ;
						SuperShotY[i] = PlayerY - 16 ;

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

						if( SuperShotSoundFlag == 0 )
						{
							PlaySoundMem( SuperShotSound , DX_PLAYTYPE_BACK , TRUE ) ;
							ChangeVolumeSoundMem( 1 , SuperShotSound ) ;
							SuperShotSoundFlag = 1 ;
							if( SuperShotSoundFlag == 1 )
							{
								SuperShotSoundFlag = 0 ;
							}
						}	

						// 一つ弾を出したので弾を出すループから抜けます
						break ;
					}
				}
			}
			}

			if( CheckHitKey( KEY_INPUT_Z) )
			{
				for( v = 0 ; v < SHOT ; v ++ )
				{
					if( ShotFlag[v] == 0)
					{
						ShotX[v] = PlayerX + 48 ;
						ShotY[v] = PlayerY - 22 ;

						ShotFlag[v] = 1 ;
						if( ShotSoundFlag == 0 )
						{
							PlaySoundMem( ShotSound , DX_PLAYTYPE_BACK , FALSE ) ;
							ChangeVolumeSoundMem( 1 , ShotSound ) ;
							ShotSoundFlag = 1 ;
							if( ShotSoundFlag == 1 )
							{
								ShotSoundFlag = 0 ;
							}
						}	
						break ;
					}
				}
			}

			// 自機が画面左端からはみ出そうになっていたら画面内の座標に戻してあげる
			if( PlayerX < 99 ) PlayerX = 99 ;

			// 自機が画面右端からはみ出そうになっていたら画面内の座標に戻してあげる
			if( PlayerX > 509 - 96 ) PlayerX = 509 - 96  ;

			// 自機が画面上端からはみ出そうになっていたら画面内の座標に戻してあげる
			if( PlayerY < 0 ) PlayerY = 0 ;

			// 自機が画面下端からはみ出そうになっていたら画面内の座標に戻してあげる
			if( PlayerY > 480 - 128 ) PlayerY = 480 - 128 ;

			// 自機を描画
			DrawGraph( PlayerX , PlayerY , PlayerGraph , TRUE ) ;
		}

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

					// 画面外に出てしまった場合は存在状態を保持している変数に0(存在しない)を代入する
					if( SuperShotY[ i ] < -32 )
					{
						SuperShotFlag[ i ] = 0 ;
					}
				
					// 画面に弾iを描画する
					DrawGraph( SuperShotX[ i ] , SuperShotY[ i ] , SuperShotGraph , TRUE ) ;
				}
			}
			GreenGraph = NULL ;
			GreenGraph = BlueGraph ;
		}

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

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

				// 画面に弾vを描画する
				DrawGraph( ShotX[ v ] , ShotY[ v ] , ShotGraph , TRUE ) ;
			}
		}
		
		// 敵の移動ルーチン 
		for( e = 0 ; e < ENEMY ; e ++ )
		{
			if( EnemyY[e] == 480)
			{
					EnemyFlag[e] = 2 ;
			}
		}
		if(EnemyFlag[0] == 1 )
		{
			DrawGraph( EnemyX[0] , EnemyY[0] , EnemyGraph , TRUE ) ;
			EnemyY[0] += 2 ;
		}
		if( EnemyFlag[0] == 2 )
		{
			EnemyClearCounter[0] ++ ;
			if( EnemyClearCounter[0] == 50 )
			{
				EnemyFlag[1] = 1 ;
			}
		}
		if(EnemyFlag[1] == 1 )
		{
			DrawGraph( EnemyX[1] , EnemyY[1] , EnemyGraph , TRUE ) ;
			EnemyY[1] += 2 ;
		}
		if( EnemyFlag[1] == 2 )
		{
			EnemyClearCounter[1] ++ ;
			if( EnemyClearCounter[1] == 50 )				
			{
				EnemyFlag[2] = 1 ;
			}
		}
		if(EnemyFlag[2] == 1 )
		{
			DrawGraph( EnemyX[2] , EnemyY[2] , EnemyGraph , TRUE ) ;
			EnemyY[2] += 2 ;
		}
		if( EnemyFlag[2] == 2 )
		{
			EnemyClearCounter[2] ++ ;
			if( EnemyClearCounter[2] == 50 )				
			{
				EnemyFlag[3] = 1 ;
				EnemyFlag[4] = 1 ;
				EnemyFlag[5] = 1 ;
			}
		}
		if(EnemyFlag[3] == 1 )
		{
			DrawGraph( EnemyX[3] , EnemyY[3] , EnemyGraph , TRUE ) ;
			EnemyY[3] += 2 ;
		}
		if(EnemyFlag[4] == 1 )
		{
			DrawGraph( EnemyX[4] , EnemyY[4] , EnemyGraph , TRUE ) ;
			EnemyY[4] += 2 ;
		}
		if(EnemyFlag[5] == 1 )
		{
			DrawGraph( EnemyX[5] , EnemyY[5] , EnemyGraph , TRUE ) ;
			EnemyY[5] += 2 ;
		}


		for( v = 0 ; v < SHOT ; v ++ )
		{
			for( e = 0 ; e < ENEMY ; e ++ )
			{
			// 弾iが存在している場合のみ次の処理に移る
			if( ShotFlag[ v ] == 1 )				
			{
				if( EnemyFlag[e] == 1 )
				{
					// 四角君との当たり判定
					if( ( ( ShotX[v] > EnemyX[e] && ShotX[v] < EnemyX[e] + 64 ) ||
						( EnemyX[e] > ShotX[v] && EnemyX[e] < ShotX[v] + 32 ) ) &&
			            ( ( ShotY[v] > EnemyY[e] && ShotY[e] < EnemyY[e] + 64 ) ||
						( EnemyY[e] > ShotY[v] && EnemyY[e] < ShotY[v] + 32 ) ) )
					{
						// 接触している場合は当たった弾の存在を消す
						ShotFlag[ v ] = 0 ;
						EnemyFlag[e] = 2 ;
						score += 10 ;
					}
				}
			}
			}
		}

		if( score >= 100 )
		{
			for( i = 0 ; i < SUPER_SHOT ; i ++ )
			{
				for( e = 0 ; e < ENEMY ; e ++ )
				{
				// 弾iが存在している場合のみ次の処理に移る
				if( SuperShotFlag[ i ] == 1 )
				{
					if( EnemyFlag[e] == 1 )
					{
						// 四角君との当たり判定
						if( ( ( SuperShotX[i] > EnemyX[e] && SuperShotX[i] < EnemyX[e] + 64 ) ||
							( EnemyX[e] > SuperShotX[i] && EnemyX[e] < SuperShotX[i] + 32 ) ) &&
							( ( SuperShotY[i] > EnemyY[e] && SuperShotY[i] < EnemyY[e] + 64 ) ||
							( EnemyY[e] > SuperShotY[i] && EnemyY[e] < SuperShotY[i] + 32 ) ) )
						{
							// 接触している場合は当たった弾の存在を消す
							SuperShotFlag[ i ] = 0 ;
							EnemyFlag[e] = 2 ;
						}
					}
				}
				}
			}
		}

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


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

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

	END :

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

	return 0 ;					// ソフトの終了
}
わかりにくくてすいません。
このプログラムを実行すると、自機のX座標と敵のX座標が同じ場合ZKeyを押した瞬間敵が消えます。
わかりにくかったら実行してみて下さい。
なぜこうなるのか教えて下さい。
[/color]


A


アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: 当たり判定

#2

投稿記事 by パコネコ » 9年前

コード:

if( ( ( ShotX[v] > EnemyX[e] && ShotX[v] < EnemyX[e] + 64 ) ||
                        ( EnemyX[e] > ShotX[v] && EnemyX[e] < ShotX[v] + 32 ) ) &&
                        ( ( ShotY[v] > EnemyY[e] && ShotY[e] < EnemyY[e] + 64 ) ||
                        ( EnemyY[e] > ShotY[v] && EnemyY[e] < ShotY[v] + 32 ) ) )
この部分が間違ってるようです。

ShotXとYがv
EnemyXとYがe

のようですが、
ShotY[e]
とeになってしまってます。
おそらくここがミスなのだと思います。
一度直してみてください。

コード:

if( ( ( ShotX[v] > EnemyX[e] && ShotX[v] < EnemyX[e] + 64 ) ||
                        ( EnemyX[e] > ShotX[v] && EnemyX[e] < ShotX[v] + 32 ) ) &&
                        ( ( ShotY[v] > EnemyY[e] && ShotY[v] < EnemyY[e] + 64 ) ||
                        ( EnemyY[e] > ShotY[v] && EnemyY[e] < ShotY[v] + 32 ) ) )
こんな感じにゃ。
ニャン!!\(゜ロ\)(/ロ゜)/

KSK
記事: 79
登録日時: 9年前

Re: 当たり判定

#3

投稿記事 by KSK » 9年前


ありがとうございます!
出来ました!


A


閉鎖

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