1. 無職の学び舎
  2. >
  3. 無職はゲーム数学の勉強をする
  4. >
  5. 円と円の衝突

円と円の衝突

ここでは円と円の衝突判定についてまとめていきます。

円と円の衝突判定は簡単で、かつ処理も軽く、衝突判定の中では最もよく使われる1番人気の衝突判定だと思います。

考え方

2つの円があります。

円の中心をそれぞれ$C_{1}, C_{2}$、とします。

円の半径をそれぞれ$r_{1}, r_{2}$、とします。

円が衝突しているかどうかは $C_{1}$ から $C_{2}$ までの距離と2つの円の半径の和をを比較します。

比較した結果、$C_{1}$ から $C_{2}$ までの距離が2つの円の半径の和より小さくなっていれば、円と円は衝突しています。

計算方法

円の中心をそれぞれ$C_{1}, C_{2}$、円の半径をそれぞれ$r_{1}, r_{2}$とします。

2つの円の中心の距離を求めたいので、$C_{1}$ から $C_{2}$に向かうベクトル、$\vec{C_{1}C_{2}}$を求めます。

$\vec{C_{1}C_{2}}$ は $C_{2}$ の座標から $C_{1}$ の座標を引き算することで求まります。

$\vec{C_{1}C_{2}} = C_{2} - C_{1}$

あとは2つの円の半径の和と $\vec{C_{1}C_{2}}$ の長さを比較するだけとなります。

$|\vec{C_{1}C_{2}}| < r_{1} + r_{2} $ であれば、2つの円は衝突している。

処理負荷対策

プログラムで円と円の衝突を判定する場合は、ちょっとした工夫をすることで処理負荷を下げる事ができます。

$\vec{C_{1}C_{2}}$ の成分を $(x, y)$ とすると、$|\vec{C_{1}C_{2}}|$ の長さは三平方の定理より

$|\vec{C_{1}C_{2}}| = \sqrt{x^2 + y^2}$ となります。

2つの円の半径の和との比較は以下のように表せます。

$|\vec{C_{1}C_{2}}| < r_{1} + r_{2}$
$\sqrt{x^2 + y^2} < r_{1} + r_{2}$
$x^2 + y^2 < (r_{1} + r_{2})^2$

プログラムで平方根の計算は重いので、上記のように2つの円の半径の和を二乗したものと判定することで平方根の計算をしないですみます。

サンプルコード

/**
 * 円と円が当たっているかどうか
 * @param circle1 円1
 * @param circle2 円2
 */
function isHit(circle1:Circle, circle2:Circle) 
{
  // 円1から円2の中心に向かうベクトルを v とする
  const v = Vector2.sub(circle2.p, circle1.p);
 
  // v の長さが 2つの円の半径の和より小さければ当たっている
  // (処理負荷対策で平方根を使わないようにしている)
  return (v.sqrMagnitude < (circle1.r + circle2.r)**2);
}