敵を自機に向かせるプログラム

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

敵を自機に向かせるプログラム

#1

投稿記事 by 奥兵 » 14年前

 シューティングのようなものを作っています、その中で敵に自機の方向を向かせようとしました。
それ自体はできたのですが、自機が敵の右上に行くと、敵が遠いほうから(遠回りして)自機を向こうとします。
角度的に小さいほうに動くようにしたいのでが、うまくできません。
どなたか手ほどきお願いします。
VC++2008、DXライブラリを使用していて、OSは7です。
一応 全コード載せます。

コード:


#include <math.h>

#include "DxLib.h"
#define PI 3.141592654

char Key[256];
struct uni{
		int image[5];
		double x,y;
		double rad;
		int HP;
		 
	};
struct enemys{

		int image[5];	 
		double x,y;
		double rad;
		int HP;

	};
struct bullet{
		 
		double x,y;
		int    fl;
		double rad;

};
struct zyoukyou {
		 
		int image[5];
		int speed;
		int count;
		//int hunteicount;
	
};
void dainyuu(struct uni *mainuni,struct enemys *ene ,struct bullet *bullet,struct zyoukyou *fase){
	int i;
	
	mainuni->x=300;
	mainuni->y=600;
	mainuni->image[0]=LoadGraph("usvmm1.png");

	ene->image[0]=LoadGraph("ene1.png");
	ene->image[1]=LoadGraph("ene2.png");
	ene->rad=1;
	ene->x=300;
	ene->y=100;
	ene->HP=4000;

	for(i=0;i<30;i++){
	     bullet[i].fl=0;	
	}
	 
		fase->image[0]=LoadGraph("bullet.png");
		fase->speed=10;
		fase->count=5;
	//	fase->hunteicount=0;
} 
void attack(struct bullet *bullet,struct uni *mainuni,struct zyoukyou *fase){	
	 	int i;
		fase->count++;
	 
		if( CheckHitKey( KEY_INPUT_RETURN ) == 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;
			   }

			}
		}
		 
}
 void enemy(struct enemys *ene,struct uni *mainuni,struct bullet *bullet){
	int White;
	White=GetColor(0,55,55);
	int i ;
	double rad,flg;
	
	rad=(((mainuni->rad)+PI/2));
	 
	 //↓問題の地点はここです
	if((ene->rad)>=(rad)){
		ene->rad=(ene->rad)-(0.01);
	} 
	if((ene->rad)<=(rad)){
		ene->rad=(ene->rad)+(0.01);
	}
 
	
	DrawRotaGraph((int)ene->x,(int)ene->y,1.0,ene->rad, ene->image[0], TRUE );
	 
 
	//DrawFormatString(100,200, White , "x=%d    y=%d      " ,ene->HP,(int)(ene->rad-rad)%(int)PI/2);
	 
}
void huntei(struct bullet *bullet,struct uni *mainuni,struct zyoukyou *fase,struct enemys *ene){
		int White;
		White=GetColor(0,255,255);
		int i,range;
		 range=30*30;
	
	for(i=0;i<30;i++){
		if((range>((ene->x-bullet[i].x)*(ene->x-bullet[i].x)+(ene->y-bullet[i].y)*(ene->y-bullet[i].y))&&(bullet[i].fl==1))){
			bullet[i].fl=0;
			ene->HP-=10;
		}
	}
	//DrawFormatString(100,200, White , "x=%d y=%d mx=%d " ,ene->HP,3,3);
}
 
void move(struct uni *mainuni,struct enemys *ene){
	double x,y,cx,cy,s;
	x=0;
	y=0;
	s=3;
    int White;
	White=GetColor(255,255,25);
	if((mainuni->x>-30)){
		if( CheckHitKey( KEY_INPUT_A ) == 1 ){
		x=-s;
		}
	}
	if((mainuni->y<570)){
		if( CheckHitKey( KEY_INPUT_S ) == 1 ){
			y=s;
		}
	}
	if((mainuni->x<770)){
		if( CheckHitKey( KEY_INPUT_D ) == 1 ){
			x=s;
		}
	}
	if((mainuni->y>-30)){
		if( CheckHitKey( KEY_INPUT_W ) == 1 ){
			y=-s;
		}
	}
	cx=pow((ene->x-(mainuni->x+x)),2);
    cy=pow((ene->y-(mainuni->y+y)),2);
		 
	if((cx+cy)>=(60*60)){
	//	DrawFormatString(100,140, White , "判定発生"  );
		mainuni->x=mainuni->x+x;	
		mainuni->y=mainuni->y+y;
	}/*else{
		mainuni->x=mainuni->x+x;	
		mainuni->y=mainuni->y+y;
	}*/
	
	mainuni->rad=atan2(ene->y-mainuni->y,ene->x-mainuni->x);

	
	DrawRotaGraph( (int)mainuni->x, (int)mainuni->y,1.0,mainuni->rad+PI/2, mainuni->image[0], TRUE ); 
	 DrawFormatString(100,100, White , "x=%d y=%d mx=%d " ,(int)cx,(int)cy,(int)mainuni->x);
	 
}
int map(int mapimg){
		
		DrawGraph(0,0,mapimg,TRUE);
	
return 0;
}
int battle(){
	
	int mapimg;
	mapimg=LoadGraph("usmap1.png");	
	 
	
	struct uni mainuni;
	struct enemys ene;
	struct zyoukyou fase;
	struct bullet bullet[30];
	dainyuu(&mainuni,&ene,bullet,&fase);
	while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
	
 
	map(mapimg);
 
	attack(bullet,&mainuni,&fase);
	enemy(&ene,&mainuni,bullet);
	move(&mainuni,&ene);
	huntei(bullet,&mainuni,&fase,&ene);
	ScreenFlip();
	}
 return 0;
}	
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
		SetGraphMode( 800 , 600 , 32 ) ;
        if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
        SetDrawScreen( DX_SCREEN_BACK );        //裏画面に設定
		
        while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
            
                //int story();

				battle();
                ScreenFlip();
        }
 
        DxLib_End();
        return 0;
}


アバター
a5ua
記事: 199
登録日時: 14年前

Re: 敵を自機に向かせるプログラム

#2

投稿記事 by a5ua » 14年前

こんな感じでどうでしょうか?

コード:

	// 敵から自機へ向かう角度
	rad = atan2(mainuni->y - ene->y, mainuni->x - ene->x);

	double d = rad - ene->rad;	// 角度の差

	// どちらに回るか判定(ベクトルの外積の考え方を使っています)
	if (sin(d) > 0) {
		ene->rad += 0.01;
	} else {
		ene->rad -= 0.01;
	}

奥兵

Re: 敵を自機に向かせるプログラム

#3

投稿記事 by 奥兵 » 14年前

ご指摘の通り直したら思い通り動いてくれました。
素早い御返事ありがとうございます^^

アバター
GRAM
記事: 164
登録日時: 14年前
住所: 大阪

Re: 敵を自機に向かせるプログラム

#4

投稿記事 by GRAM » 14年前

まずは角度の表現ですが、
atan2を用いる前提で考えます(つまり、x軸基準y軸方向正の回転、表現-180~180:説明の便宜上。実際にはラジアンで構わない)

要するに境界をまだぐことに失敗しているのだと思います。
解決法はいくつかありますが、角度のみに頼るやり方を提案します

φを現在の敵の角度  Θを敵から自機への角度とすると
φ=60 Θ=70は簡単で70-60=10度プラスすると求まるけれど
たとえばφ=178, Θ= -178が問題の数字ですね
ここから4度プラスするという解を導き出す方法を考えればいいわけです。

問題はこいつらが±180度境界をまたいでいることに集約されます。
境界を取っ払ってしまえばいいのでしょう
つまるところφとΘの差の絶対値が180度以上あることが問題なわけです(こうなるとどう頑張っても±180度境界をまたぐ)
これを検出して360でも足し引きしてやりましょう

コード:

if (φ - Θ > 180) {
    Θ += 360;
}elseif (φ - Θ < 180) {
    Θ -= 360;
}
これであとは先と同じようにΘ-φをしてやればいいと思います
シミュレーションしてみましょう
さっきの奴だと(-178)-(+178) = -356ですが
Θから360をひいてやると
-178 - (-182) = 4となり 目的の答えが得られます!

奥兵

Re: 敵を自機に向かせるプログラム

#5

投稿記事 by 奥兵 » 14年前

どこが問題なのか詳しく書いていただきありがとうございます。
おかげでなぜ駄目だったのか、どうしてそうすればいいのか理解できました。

閉鎖

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