こちら数学?が主な内容となっております。そして死ぬほど間違っております。まあまああっていると思うのでご参考程度にお願いします。そして2Dゲームを想定しています。
特にあたり判定とかについて調べたわけでもなく、私の試行錯誤で作ったものだらけです。こんな記事読まずにSIV3Dの物理を参考にしましょう。
必要な条件
あたり判定といってもただ当たったというのがわかるだけでは足りません。どこに当たって、その法線ベクトルはどれかなどがわからないと物理的な動きをさせられないです。
・当たっていることがわかる
・どの場所で当たったかわかる
・高速で物体が動いているときもすり抜けないようにする
以上の条件が必要です。
当たっていることがわかる
基本的には全ての物体は辺の集まりでできています。なので辺と辺が交差していたら当たっているとみなしてよいはずです。
辺と辺が交差しているか調べる式はこの通りです
kousaman.cs
float ax1,ay1,ax2,ay2;
float bx1,by1,bx2,by2;
double c1=(ax2-ax1)*(by1-ay1) - (ay2-ay1)*(bx1-ax1);
double c2=(ax2-ax1)*(by2-ay1) - (ay2-ay1)*(bx2-ax1);
double c3=(bx2-bx1)*(ay1-by1) - (by2-by1)*(ax1-bx1);
double c2=(bx2-bx1)*(ay2-by1) - (by2-by1)*(ax2-bx1);
if(c1*c2<0&&c3*c4<0)
{
Console.WriteLine("kousa!!");
}
これで線の交差を判定できますね♡
詳しくは
さらに、小さい図形が大きい図形にすっぽり収まってしまったときのことを考えると、領域内に点があるかどうか判定する関数も必要です。これは図形ごとに違います。円であれば簡単ですが多角形は回転角度を考慮しなければならないためちょっとめんどくさいです。
円は頂点がありませんが適当に円周を分割して頂点としちゃいましょう。
この二つがあれば特定の図形二つがぶつかっているか否かを判定できます。
どの場所で当たったかわかる
物理的な動きをさせるためには当たった個所の面を特定する必要があります。
厳密なシミュレーションは不可能なので1フレーム前の位置関係からどの辺にぶつかったかを特定しましょう。多分これでまあまあうまくいきます。
なのでこんなメソッドを作ります。これは四角形の場合ですね。
Rectangle.cs
public override double gethosen(float px, float py)
{
float dx = px - gettx();
float dy = py - getty();
//これで回転も含めて相対座標に変える
double ddx = dx * Math.Cos(-rad) - dy * Math.Sin(-rad);
double ddy = dx * Math.Sin(-rad) + dy * Math.Cos(-rad);
double b = Math.Atan2(h, w);
double a = Math.Atan2(ddy, ddx);
double res ;
//後は角度によって4つに場合分けする。回転を足すのを忘れずに
if (-b <= a && a <= b) res= rad;
else if (b <= a && a <= Math.PI - b) res= Math.PI / 2 + rad;
else if(-Math.PI + b <= a && a <= -b) res= -Math.PI / 2 + rad;
else res= Math.PI+rad;
return Math.Atan2(Math.Sin(res), Math.Cos(res));
}
そして次のイメージで移動する距離を決めます。
下手ですが十字の交わるところが四角形に中心だと思ってください。
橙は法線ベクトルで標準化した点の中で最も中心との差が小さい(-負の距離も含む)点で求められます。すいません国語力がないのでまとめに言葉で説明できません。
青の求め方は簡単ですね。
後は橙+青に中心を移動させればよいのです。しかしこれにも問題があります。
こういう場合判定をしてしまうと瞬間移動したみたいになってしまいますので
こう、基準となる図形を変えればいい感じになります。なので移動距離が小さい方を採用するとまあまあうまくいきます。
高速で物体が動いているときもすり抜けないようにする
物体が高速移動するとすり抜けてしまうのでそれを防止するためにこんなイメージでやりましょう。
一フレーム前の図形の頂点と新しく線分を作り、その線分で判断すれば割とどうにかなります。多分線が交差しないパターンは全部点が含まれるパターンでカバーできると思います
最後に
あたり判定を厳密にやろうとすればするほど重くなっていきます。なので自分のゲームに最適なあたり判定の程度にしましょう。
↧