四角形と円の当たり判定

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

四角形と円の当たり判定

#1

投稿記事 by 雪印 » 11年前

四角形と円の当たり判定がうまく動作しません。

・参考にしたページ
http://dixq.net/rp/34.html

四角形と円の判定を3つに分けて判定しています。
円と、四角形の4点の接触判定はできるのですが、
ベクトルを使用した処理(下2つ)がうまく動きません。
どうしたらいいでしょうか?

コードでは四角形=Block 円=Ballとしてます。
GetXCorner()とGetYCorner()で四角形の4つの角は取得します。
0,1,2,3のint型の引数を与えて、それぞれ左上、右上、右下、左下の座標を返します。

コード:

bool BlockBall(CBlock* tmpBlock,CBall* tmpBall){
//①Blockの角が円の中に入っていないか
		for(int i=0;i<4;i++){
			if((tmpBlock->GetXCorner(i)-tmpBall->GetX())*(tmpBlock->GetXCorner(i)-tmpBall->GetX())+
				(tmpBlock->GetYCorner(i)-tmpBall->GetY())*(tmpBlock->GetYCorner(i)-tmpBall->GetY())<=
				tmpBall->GetRadius()*tmpBall->GetRadius()){
					return true;
			}
		}

// ②ベクトル C→P と C→Q のなす角θおよび回転方向を求める
        Vector2_t c, p, q; // 入力データ
        Vector2_t cp;      // ベクトル C→P
        Vector2_t cq;      // ベクトル C→Q
        double s;          // 外積:(C→P) × (C→Q)
        double t;          // 内積:(C→P) ・ (C→Q)
        double theta,theta2;// θ (ラジアン)

        // c,p,q を所望の値に設定する
		q.x = tmpBall->GetX();      q.y = tmpBall->GetY();//円の中心座標

		c.x = tmpBlock->GetXCorner(0);  c.y = tmpBlock->GetYCorner(0);//左上
        p.x = tmpBlock->GetXCorner(1);  p.y = tmpBlock->GetYCorner(1);//右上

        // 回転方向および角度θを計算する
        Vector2Diff(&cp, &p, &c);          // cp ← p - c
        Vector2Diff(&cq, &q, &c);          // cq ← q - c
        s = Vector2OuterProduct(&cp, &cq); // s ← cp × cq
        t = Vector2InnerProduct(&cp, &cq); // t ← cp ・ cq
        theta = atan2(s, t);

		c.x = tmpBlock->GetXCorner(2);  c.y = tmpBlock->GetYCorner(2);//右下
        p.x = tmpBlock->GetXCorner(3);  p.y = tmpBlock->GetYCorner(3);//左下

        // 回転方向および角度θを計算する.
        Vector2Diff(&cp, &p, &c);
        Vector2Diff(&cq, &q, &c);
        s = Vector2OuterProduct(&cp, &cq);
        t = Vector2InnerProduct(&cp, &cq);
        theta2 = atan2(s, t);
		
		DrawFormatString(200,170,42150,"%f",PI/2);
		DrawFormatString(200,200,42150,"%f",theta);
		DrawFormatString(200,230,42150,"%f",theta2);

		if(theta<PI/2 && theta2<PI/2){
			return true;
		}


//③点と線分との距離を求める
		for(int i=0;i<4;i++){
			int t = i+1%4;//次の点

			double ax = tmpBlock->GetXCorner(t);
			double ay = tmpBlock->GetYCorner(t);
			double bx = tmpBall->GetX() - tmpBlock->GetXCorner(i);
			double by = tmpBall->GetY() - tmpBlock->GetYCorner(i);
	
				double r = (ax*bx + ay*by) / (ax*ax + ay*ay);
				double tmpx,tmpy;

				if( r<= 0 ){
					tmpx=tmpBlock->GetXCorner(i);
					tmpy=tmpBlock->GetYCorner(i);
				}else if( r>=1 ){
					tmpx=tmpBlock->GetXCorner(t);
					tmpy=tmpBlock->GetYCorner(t);
				}else{
					tmpx = tmpBlock->GetXCorner(i) + r*ax;
					tmpy = tmpBlock->GetYCorner(i) + r*ay;
				}

				if((tmpx-tmpBall->GetX())*(tmpx-tmpBall->GetX())+(tmpy-tmpBall->GetY())*(tmpy-tmpBall->GetY())<=(tmpBall->GetRadius()*tmpBall->GetRadius())){
					return true;
				}
		}

	return false;
}


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