円と円の内外判定について

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

円と円の内外判定について

#1

投稿記事 by SINA » 12年前

現在パワプロっぽいバッティングゲームを作っているのですが
ミートカーソルとボールの重なっているかの判定がうまくいきません。
色々なサイトを参考にしてみましたが進歩しません
かなり初歩的な質問だと思いますがよろしくお願いします
以下全コード

コード:

/*yakyuu*/
#include<DxLib.h>
#include<math.h>
#include <time.h> 
#define TURN_MAX 0.5//変化球の曲がる最大角度
#define PI 3.1415926535897932384//円周率
//プロトタイプ宣言
void grand();
bool CollisionCC(double r1,double r2,double x1,double x2,double y1,double y2);
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPSTR lpCmdLine, int nCmdShow )
{
 // ウインドウモードに変更
 ChangeWindowMode( TRUE );
 // DXライブラリ初期化
 if( DxLib_Init() == -1 )
  {
	 return 0;
  }
 SetDrawScreen( DX_SCREEN_BACK );
 int i;//ループ用
 /////////////////ゲーム用///////////////////
 double BallY=120;//ボール高さ
 double BallX=320;//ボール横
 double BallXEND;//ボール終点x
 double BallYEND;//ボール終点y
 double rad;//角度
 double turn;//曲がる時の角度
 double direction;//曲がる時進むべき角度
 double BallZ=1;//ボール奥行き
 double Ballkage;//ボールの影
 double BallSpeed;//速さ
 bool change=false;//変化球フラグ
 bool hit=false;//ヒットフラッグ
 

 int batterx=105;//バッターの横座標
 int battery=250;//バッターの縦
 int X=0;//ミートの横
 int Y=0;//ミートの縦
 int meat=20;//ミートの広さ

 int Cr ;
 int draw;//背景描写用


 bool SWING=false;//スイングフラッグ
 bool PITCH=true;//投球フラッグ
 bool NOWPITCH=false;//投球中フラッグ
 bool UP=false;//移動フラッグ上
 bool DOWN=false;//下
 bool LEFGT=false;//左
 bool RIGHT=false;//右

 Cr= GetColor( 255 , 255, 255 ) ;	// 白色の値を取得
 int batter[3];//バッターの画像
 int count=0;//アニメーション管理用
 LoadDivGraph( "bat.bmp" , 3, 1 , 3, 310 , 270, batter ); // 画像の分割読み込み
 //////////////////////////////////////////////////
 // srand関数で、乱数パターンを初期化する
 unsigned int    now = (unsigned int)time( 0 );
 srand( now );
 ////////////////////////////////////////////////
 


 while(1)
 {
	 
	 if(SWING==true)
	 {
		count++;
	 }
	 if( ProcessMessage() != 0 )
	 { 
		 // メッセージ処理
         break;//ウィンドウの×ボタンが押されたらループを抜ける
     }
	 ClearDrawScreen(); // 画面を消す
	 grand();//グランド描写
	 DrawBox(270,330,370,430,GetColor(255,100,0),FALSE);//ストライクゾーン
	 DrawCircle(320+X,380+Y,meat,GetColor(0,0,200),FALSE);//ミート
	 DrawCircle(320+X,380+Y,1.5,GetColor(200,0,100),TRUE);//ミート真ん中

	 if(CheckHitKey( KEY_INPUT_C) ==1&& PITCH==true)//ピッチング用
	 {
		 BallY=120;
		 BallX=320;
		 BallZ=1;
		 BallXEND=270+(int)( rand() * (370 - 270 + 1.0) / (1.0 + RAND_MAX) );
		 BallYEND=330+(int)( rand() * (430 - 330 + 1.0) / (1.0 + RAND_MAX) );
		 rad=atan2(BallYEND-BallY,BallXEND-BallX);
		 PITCH=false;
		 NOWPITCH=true;
	 }
	 if( CheckHitKey( KEY_INPUT_Z) == 1 && SWING==false)//Zが入力されている
	 {
		 SWING=true;
	 }

	 ////////////////////カーソル移動/////////////////////////////////////////
	 if( CheckHitKey( KEY_INPUT_UP) == 1&&-50<=Y && SWING==false)//上
	 {
		 Y-=3;
	 }
	 if( CheckHitKey( KEY_INPUT_RIGHT) == 1&&X<=50 && SWING==false)//右
	 {
		 X+=3;
	 }
	 if(CheckHitKey( KEY_INPUT_LEFT) == 1&&-50<=X && SWING==false)//左
	 {
		 X-=3;
	 }
	 if( CheckHitKey( KEY_INPUT_DOWN) == 1&&Y<=50 && SWING==false)//下
	 {
		 Y+=3;
	 }
	 /////////////////////////////////////////////////////////////////////////////

	 if(SWING==true&&count<=5)//スイングの構えと途中の切り替え
	 {
		DrawGraph( batterx+X, battery, batter[1], TRUE ); //バッタースイング画像
		///////////////ミートの判定//////////////////////////////
		if(7.5>=BallZ&&BallZ>=5&&CollisionCC(6,meat,BallXEND,X,BallYEND,Y)==true)
		{
			hit=true;
			BallY-=5;
		}
	 }
	 
	 else if(SWING==true && NOWPITCH==true||5<count&&count<=50)//スイングして0.5秒後に振り終わりに
	 {
		DrawGraph( batterx+X, battery, batter[2], TRUE ); //バッタースイング2画像
	 }
	 else if(SWING==true&&PITCH==true)//振り終わって訳1秒後にフラッグをfalse
	 {
		 SWING=false;
		 count=0;
	 }
	 else
	 {
		DrawGraph( batterx+X, battery, batter[0], TRUE ); //バッター画像
	 }
	 //////////////////ボールの影定義//////////////
	 if(400<=BallYEND)
	 {
		Ballkage=50;//高さ90,70,50,
	 }
	 else if(BallYEND<=360)
	 {
		Ballkage=90;//高さ90,70,50,
	 }
	 else
	 {
		Ballkage=70;
	 }
	 ///////////////////////////////////////////////
	 if(NOWPITCH==true)
	 {
		DrawCircle( BallX , BallY , BallZ , Cr , TRUE) ;// ボールを描画
		DrawCircle( BallX , BallY +Ballkage, BallZ-2, GetColor(0,0,0) , TRUE) ;//ボールの影
		DrawCircle( BallXEND ,BallYEND, 6, GetColor(255,0,0) , FALSE);//ストライクゾーンのボール
	 }
	 if(BallZ<=8)
	 {
		BallZ=BallY/60;
	 }
	 if(BallY>=540)
	 {
		NOWPITCH=false;
		PITCH=true;
	 }
	 BallSpeed=5;
	 if(NOWPITCH==true)
	 {
		if(hit==false)
		{
			BallY+=sin(rad)*BallSpeed;//ボールの縦ベクトル
			BallX+=cos(rad)*BallSpeed;//ボールの横ベクトル
		}

	 }
	 DrawFormatString( 30, 30, Cr, "BallZ=%f", BallZ ) ;//デバッグ用
	 DrawFormatString( 30, 50, Cr, "BallX=%f", BallX ) ;//デバッグ用
	 DrawFormatString( 30, 70, Cr, "BallY=%f", BallY ) ;//デバッグ用
	 DrawFormatString( 30, 90, Cr, "rad=%f", rad) ;//デバッグ用
	 ScreenFlip(); //裏画面を表画面に反映
 }
 DxLib_End() ;			// DXライブラリ使用の終了処理
 return 0;
}


bool CollisionCC(double r1,double r2,double x1,double x2,double y1,double y2)
{
	// 円同士の当たり判定
	double r = r1 + r2;   // 2円の半径の合計
	double x = x1 - x2;   // X座標の差
	double y = y1 - y2;   // Y座標の差
	if(r*r >= x*x + y*y)
	{
		return true;
	}
	else
	{
		return false;
	}
}


void grand()
{
 int Cr ;
 int Cr2;
 int Cr3;
 int Cr4;
 Cr= GetColor( 255 , 255, 255 ) ;	// 白色の値を取得
 Cr2= GetColor(0,120,0);//緑
 Cr3= GetColor(186,125,50);//茶色
 Cr4= GetColor(136,75,20);//こい茶色

 DrawBox( 0 , 0 , 640 , 480 , Cr2 , TRUE) ;//緑で塗りつぶす
 DrawOval(320,540,1000,500,Cr3,TRUE);//グランド
 DrawOval(320,220,70,20,Cr4,TRUE);//まうんど

 DrawBox(290,440,350,455,Cr,TRUE);//ホームベース
 DrawTriangle( 290, 455, 350, 455, 320, 470, Cr, TRUE);//ホームベース2

 DrawLine(270,410,260,480,Cr,5);//バッターボックス
 DrawLine(270,410,130,410,Cr,5);//バッターボックス2
 DrawLine(130,410,110,480,Cr,5);//バッターボックス3

 DrawLine(370,410,380,480,Cr,5);//バッターボックス1
 DrawLine(370,410,510,410,Cr,5);//バッターボックス2
 DrawLine(510,410,530,480,Cr,5);//バッターボックス3

 DrawLine(200,410,0,310,Cr,5);//ライン左
 DrawLine(440,410,640,310,Cr,5);//ライン右
}
恐らく下記辺りのコードに間違いがあると思うのですが

コード:

if(SWING==true&&count<=5)//スイングの構えと途中の切り替え
	 {
		DrawGraph( batterx+X, battery, batter[1], TRUE ); //バッタースイング画像
		///////////////ミートの判定//////////////////////////////
		if(7.5>=BallZ&&BallZ>=5&&CollisionCC(6,meat,BallXEND,X,BallYEND,Y)==true)
		{
			hit=true;
			BallY-=5;
		}
	 }
///////////////////////////////////////////////////////////////////////////
bool CollisionCC(double r1,double r2,double x1,double x2,double y1,double y2)
{
	// 円同士の当たり判定
	double r = r1 + r2;   // 2円の半径の合計
	double x = x1 - x2;   // X座標の差
	double y = y1 - y2;   // Y座標の差
	if(r*r >= x*x + y*y)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//////////////////////////////////////////////////////////////////////////////////
 

アバター
ぱにしん
記事: 58
登録日時: 14年前
住所: 滋賀

Re: 円と円の内外判定について

#2

投稿記事 by ぱにしん » 12年前

野球ゲームですか。
そういえばこういうの作ってる人見たのは始めてなような・・・
スポーツ系のゲームも面白そうです。

パッと見ですが、問題点はCollisionCC関数の

コード:

    if(r*r >= x*x + y*y)
    {
        return true;
    }
この部分ですね。
二円の中心同士の距離の方が小さくなければ衝突という事にはなりませんよね?

それはさておき、私のような者が他人のソースの内容をどうこう言うのは凄く気が引けますが、
一つの関数の中に全ての処理を書いてしまっていて、かなり読みにくくなってしまっています。
どこで何をしているのかよく分かりません。

ゲームプログラミングの館の方で「ゲームプログラミング設計」という項目があるので、そちらを読まれては如何でしょうか。
あと、ついでですが、grandは恐らくgroundの誤記ですね。

derok
記事: 51
登録日時: 12年前

Re: 円と円の内外判定について

#3

投稿記事 by derok » 12年前

SINA さんが書きました: 恐らく下記辺りのコードに間違いがあると思うのですが

コード:

if(SWING==true&&count<=5)//スイングの構えと途中の切り替え
     {
        DrawGraph( batterx+X, battery, batter[1], TRUE ); //バッタースイング画像
        ///////////////ミートの判定//////////////////////////////
        if(7.5>=BallZ&&BallZ>=5&&CollisionCC(6,meat,BallXEND,X,BallYEND,Y)==true)
        {
            hit=true;
            BallY-=5;
        }
     }
///////////////////////////////////////////////////////////////////////////
bool CollisionCC(double r1,double r2,double x1,double x2,double y1,double y2)
{
    // 円同士の当たり判定
    double r = r1 + r2;   // 2円の半径の合計
    double x = x1 - x2;   // X座標の差
    double y = y1 - y2;   // Y座標の差
    if(r*r >= x*x + y*y)
    {
        return true;
    }
    else
    {
        return false;
    }
}
//////////////////////////////////////////////////////////////////////////////////
X.Yはバッターボックスの中心をからどれ位ずれているかを表す変数で、
直接ミートの座標を表している訳ではないですよね?
ですが、CollisionCCの第四引数、第六引数はこの場合ミートの座標を指定しています。
つまり、

コード:

        if(7.5>=BallZ&&BallZ>=5&&CollisionCC(6,meat,BallXEND,X,BallYEND,Y)==true)
ではなく、

コード:

        if(7.5>=BallZ&&BallZ>=5&&CollisionCC(6,meat,BallXEND, (320+X) ,BallYEND,(380+Y) )==true)
だと思います。

SINA

Re: 円と円の内外判定について

#4

投稿記事 by SINA » 12年前

お二方ともどうも有難うございます。原因はご指摘の通りでした・・・ 座標指定も条件定義も間違えていました。
このミスはばにしんさんのご指摘の通りソースコードが見づらい事も関係が大いにありそうなので1から勉強してきますorz
有難うございました。

閉鎖

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