角度での当たり判定

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

角度での当たり判定

#1

投稿記事 by 奥兵 » 14年前

敵機への当たり判定で角度によって攻撃が有効か無効か判断するプログラムがうまく書けず
ここで質問して問題点を理解し、解決出来たと思ったのですが、動かしているうちに全然解決できていないことが判明してしまいました

ある敵機は正面からは攻撃を受け付けず裏側に回り込まなければならない。みたいな事をやりたいのですが・・・
 内容は俯瞰目線のシューティングで敵機や自機の向いている方向は状況によって360°変化します

あと自機の画像と弾丸の画像は↑方向で敵機は↓を向いています。

VC++2008 DXライブラリを使用していて OSは7です

とりあえず問題に直接関係ありそうな関数を載せます。

問題の判定部分は  huntei です
弾の角度はattackで代入されます
敵の角度はenemy自機はmoveです

コード:

void attack(struct bullet *bullet,struct uni *mainuni,struct zyoukyou *fase){	
	 	int i,mfl,mflc;
		double x,y;
		mfl=0;
		mflc=0;
		fase->count++;
	 
		if((CheckHitKey( KEY_INPUT_RETURN ) == 1  )&&(mainuni->clock==0)){ 
			if(mainuni->body==0){
				mainuni->body=12;
			}else
			if(mainuni->body==12){
				mainuni->body=13;
			}else
			if(mainuni->body==13){
				mainuni->body=0;
			}
			mfl=1;
			for(i=0;i<30;i++){
				if(bullet[i].fl==0&&fase->count>=5){
					bullet[i].fl=1;

					bullet[i].rad=mainuni->rad;//弾の角度
					bullet[i].x=mainuni->x+(sin(mainuni->rad)*-10)+cos(bullet[i].rad)*20;
					bullet[i].y=mainuni->y+(cos(mainuni->rad)*10)+sin(bullet[i].rad)*20;
					fase->count=0;
				}
			}///////
		}

		for(i=0;i<30;i++){
			if((bullet[i].fl)==1){
			   bullet[i].x+=cos(bullet[i].rad)*fase->speed;
			   bullet[i].y+=sin(bullet[i].rad)*fase->speed;
			   DrawRotaGraph( (int)bullet[i].x, (int)bullet[i].y,1.0,bullet[i].rad+PI/2,fase->image[0], TRUE );

			   if(bullet[i].x>900||bullet[i].x<-100||bullet[i].y<-100||bullet[i].y>700){
			      bullet[i].fl=0;
			   }

			}
		}
		if(mfl==1){
			
			x=(int)mainuni->x+(int)(sin(mainuni->rad)*-10)+cos(mainuni->rad)*35;
			y=(int)mainuni->y+(int)(cos(mainuni->rad)*10)+sin(mainuni->rad)*35;

			mflc=GetRand(1)+4;
			DrawRotaGraph((int) x ,(int) y , 1.0,mainuni->rad+PI/2, mainuni->image[mflc], TRUE );
		}


		if( CheckHitKey( KEY_INPUT_RBRACKET ) == 1  ){
			if(mainuni->clock==0){
				mainuni->clock=1;

			}
		}

		if(mainuni->clock>0){
			mainuni->clock+=1;
			if(mainuni->clock<7){
				mainuni->body=9;
			}else 
			if(mainuni->clock<12){
				mainuni->body=0;
			}else
			if(mainuni->clock<25){
				mainuni->body=10;	
			}else
			if(mainuni->clock<30){
				mainuni->body=11;
			}

			if(mainuni->clock>40){
				mainuni->clock=0;
				mainuni->body=0;
			}

		}


		 
}
 
 
 void enemy(struct enemys *ene,struct uni *mainuni,struct bullet *bullet,struct enebullet *ebullet,struct zyoukyou *fase){
	int White;
	int Green;
	White=GetColor(0,0,0);
	Green=GetColor(0,255,0);
    int i=0;
	double d[32];
	
	double rad[32];
	//↓敵機の角度
	for(i=0;i<32;i++){	
	if(ene->HP[i]>0){
		rad[i] = atan2(mainuni->y - ene->y[i], mainuni->x - ene->x[i])-(PI/2);
	
	 d[i] = rad[i] - ene->rad[i];
	 
		if (sin(d[i]) > 0) {
			ene->rad[i] += 0.02;
		} else {
			ene->rad[i] -= 0.02;
		}
	
	DrawBox   ( (int) ene->x[i] , (int)ene->y[i]-60 , (int)ene->x[i]+ene->HP[i] , (int)ene->y[i]-50 , Green , TRUE ) ;

		
			DrawRotaGraph((int)ene->x[i],(int)ene->y[i],1.0,ene->rad[i], ene->image[i], TRUE );
	}
	}
	
	//DrawFormatString(100,200, White , "x=%d    y=%d      " ,ene->HP,sin(d));
	 
}
//攻撃の当たり判定
void huntei(struct bullet *bullet,struct uni *mainuni,struct zyoukyou *fase,struct enemys *ene,struct obj *obj){
		int White;
		White=GetColor(0,0,0);
		int i,j,range;
		int x,y;
		double radc;
		double erad;
		double brad;
	
		DrawFormatString(100,200, White , "x=%d " ,(mainuni->rad*(180/PI)));
					 


	for(j=0;j<32;j++){		
		range=ene->size[j]*ene->size[j];
	for(i=0;i<30;i++){
		if((range>((ene->x[j]-bullet[i].x)*(ene->x[j]-bullet[i].x)+(ene->y[j]-bullet[i].y)*(ene->y[j]-bullet[i].y))&&(bullet[i].fl==1))){	

				if(ene->HP[j]>0){
					bullet[i].fl=0;

					if(j!=4){//4番が正面からは攻撃を通したくない敵
						ene->HP[j]=ene->HP[j]-1;
					}else{
				 
							erad=ene->rad[j];//試行錯誤の際に数字をいじりやすいように
							brad=bullet[i].rad;//別の変数に代入させました
					 
						radc=abs(erad-brad);//角度の差
						if(radc>(PI)){//180°以上なら360から引いた値を代入
							radc=((2*PI)-radc);
						}
					 
					 
						if((radc)>(PI/2)){//差が90°以上ならダメージ
							ene->HP[j]=ene->HP[j]-4;
						}

					}
						 

					if(ene->HP[j]<=0){
						ene->cdie[j]=25;
					}
					if(fase->tyakudann==0){

						fase->tyakudann=5;
						fase->x=(int)bullet[i].x-10;
						fase->y=(int)bullet[i].y-20;

					}
				}
		}
	}
	}
	//DrawFormatString(100,200, White , "x=%d y=%d mx=%d " ,ene->HP,3,3);
	 
	for(j=0;j<32;j++){
		range=obj->size[j]*obj->size[j];
	for(i=0;i<30;i++){
		if((range>((obj->x[j]-bullet[i].x)*(obj->x[j]-bullet[i].x)
				  +(obj->y[j]-bullet[i].y)*(obj->y[j]-bullet[i].y))&&(bullet[i].fl==1))){	
				if(obj->HP[j]>0){
					bullet[i].fl=0;
					if(fase->tyakudann==0){

						fase->tyakudann=10;
						fase->x=(int)bullet[i].x-10;
						fase->y=(int)bullet[i].y-20;
					}
				}
		}
	}
	}

	if(fase->tyakudann>0){
		fase->tyakudann-=1;
		DrawGraph( fase->x , fase->y ,mainuni->image[6+(GetRand(2))],TRUE);
	}

	
		x=(int)(mainuni->x+(sin(mainuni->rad)*10)+cos(mainuni->rad)*30);
		y=(int)(mainuni->y+(cos(mainuni->rad)*-10)+sin(mainuni->rad)*30);
	
	for(j=0;j<32;j++){	
			range=ene->size[j]*ene->size[j];
		if((mainuni->clock>12)&&(mainuni->clock<30)){
			if((range>((ene->x[j]-x)*(ene->x[j]-x)+(ene->y[j]-y)*(ene->y[j]-y)))){	
					if(ene->HP[j]>0){
						ene->HP[j]=ene->HP[j]-3;		 
						//mainuni->clock=30;
					}
					if(ene->HP[j]<=0){
						ene->cdie[j]=35;
					}
			}
		} 
	}
	

}
 
void move(struct uni *mainuni,struct enemys *ene,struct obj *obj,struct zyoukyou *fase){
	double x,y,cx[32],cy[32],s;

	x=0;
	y=0;
	s=3;
	int i;
	int	huntei=0;
    int White;
	int eneflag=0;
	White=GetColor(0,0,0);
	mainuni->move=0;
	if((mainuni->x>0)){
		if( CheckHitKey(  KEY_INPUT_A ) == 1 ){
		x=-s;
		mainuni->move=1;
		}
	}
	if((mainuni->y<590)){
		if( CheckHitKey( KEY_INPUT_S ) == 1 ){
			y=s;
			mainuni->move=1;
		}
	}
	if((mainuni->x<790)){
		if( CheckHitKey( KEY_INPUT_D ) == 1 ){
			x=s;
			mainuni->move=1;
		}
	}
	if((mainuni->y>0)){
		if( CheckHitKey( KEY_INPUT_W) == 1 ){
			y=-s;
			mainuni->move=1;
		}
	}
	
	for(i=0;i<32;i++){
		cx[i]=pow((ene->x[i]-(mainuni->x+x)),2);
		cy[i]=pow((ene->y[i]-(mainuni->y+y)),2);

		//if(ene->HP[i]<=0){
		//	ene->size[i]=0;
		//}else
		
		if(ene->HP[i]>0){
			if((cx[i]+cy[i])<(ene->size[i]*ene->size[i])+(mainuni->size*mainuni->size)){
				huntei=1;
			}
		}
	}

	for(i=0;i<32;i++){
		cx[i]=pow((obj->x[i]-(mainuni->x+x)),2);
		cy[i]=pow((obj->y[i]-(mainuni->y+y)),2);	
		 
		if((cx[i]+cy[i])<(obj->size[i]*obj->size[i])+(mainuni->size*mainuni->size)){
				huntei=1;
		}
	}


	if(huntei==0){
			DrawFormatString(100,140, White , "判定発生"  );
			mainuni->x=mainuni->x+x;	
			mainuni->y=mainuni->y+y;
	}
///////////////////////// 
		mainuni->lock2+=1;
	if(mainuni->lock2>=15){
		int chc=0; 
		if( CheckHitKey( KEY_INPUT_UP) == 1 ){
			for(i=1;i<5;i++){ 
				if((ene->HP[mainuni->rock+i]>0)&&(chc==0)&&(fase->count%8==0)){
					mainuni->rock=mainuni->rock+i;
					chc=1;
				//DrawFormatString(100,140, White , ""  );
				}	
				if(chc==1){
					break;
				}		
			}
			/*if(ene->HP[mainuni->rock+1]>0){
				mainuni->rock+=1;
				mainuni->lock2=0;
			}else
			if(ene->HP[mainuni->rock+2]>0){
				mainuni->rock+=2;
				mainuni->lock2=0;
			}
			*/
		}
		if( CheckHitKey( KEY_INPUT_DOWN) == 1 ){
			 for(i=1;i<5;i++){ 
				if((ene->HP[mainuni->rock-i]>0)&&(chc==0)&&(fase->count%8==0)){
					mainuni->rock=mainuni->rock-i;
					chc=1;
				//DrawFormatString(100,140, White , ""  );
				}	
				if(chc==1){
					break;
				}		
			}
		}

	}
	for(i=0;i<32;i++){
		if(ene->HP[mainuni->rock]<=0){
			mainuni->rock+=1;
			if(mainuni->rock==31){
				mainuni->rock=0;
			}
		}else{
		eneflag=1;
		}
	}
	if(eneflag==1){
		DrawRotaGraph( (int)ene->x[mainuni->rock], (int)ene->y[mainuni->rock],1.0,0, mainuni->image[14], TRUE );
	}

////////////////////↓自機の角度
		if(ene->HP[mainuni->rock]>0){
			mainuni->rad=atan2(ene->y[mainuni->rock]-mainuni->y,ene->x[mainuni->rock]-mainuni->x);
		}else{
			mainuni->rad=-PI/2;
		}

	mainuni->zyoutai=mainuni->zyoutai+1;
	if((mainuni->zyoutai%8)==1){
			if(mainuni->move==1){
				mainuni->walk=mainuni->walk+1;
			}
	}
	if(mainuni->walk==4){
		mainuni->walk=0;
		//mainuni->zyoutai=0;
	}
	if(mainuni->walk==0||mainuni->walk==2){
		DrawRotaGraph( (int)mainuni->x, (int)mainuni->y,1.0,mainuni->rad+PI/2, mainuni->image[1], TRUE ); //静止
	}
	if(mainuni->walk==1){
		DrawRotaGraph( (int)mainuni->x, (int)mainuni->y,1.0,mainuni->rad+PI/2, mainuni->image[2], TRUE ); //移動
	}
	if(mainuni->walk==3){
		DrawRotaGraph( (int)mainuni->x, (int)mainuni->y,1.0,mainuni->rad+PI/2, mainuni->image[3], TRUE ); //移動
	}

	DrawRotaGraph( (int)mainuni->x, (int)mainuni->y,1.0,mainuni->rad+PI/2, mainuni->image[mainuni->body], TRUE );//上半身

	DrawFormatString(100,100, White , "x=%d y=%d mx=%d " ,(int)mainuni->x,(int)mainuni->y,10);
	 
}


アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 角度での当たり判定

#2

投稿記事 by h2so5 » 14年前

解決出来ていないとはどのような状況なのでしょうか?

奥兵

Re: 角度での当たり判定

#3

投稿記事 by 奥兵 » 14年前

ええと、敵の周りをぐるぐると移動していると
敵との相対的角度は同じでありながら自機の場所によって判定があったりなかったりします。
いろいろ試行錯誤してみたんですが、たいていその現象が起こってしまします・・・

奥兵

Re: 角度での当たり判定

#4

投稿記事 by 奥兵 » 14年前

独りよがりでスイマセン、なんとか自力で解決しました。
敵の角度の制御の関数enemyで差分を判定して足し引き
する際に+-180°を超える値になっていたことと、
atan2で基準となる角度と画像の角度が違ったので合わせるために挟んだ-(PI/2)でした。
お騒がせいしてすいませんでした。

閉鎖

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