・参考にしたページ
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;
}