円どうしの重なり
相手が動く円になると、判定は二点間の距離になる。二つの円の中心の距離が、半径の和より近ければ重なっている。
距離をそのまま出すには平方根が要る。判定だけなら両辺を二乗して、距離の二乗と半径の和の二乗を比べれば、√ を一回省ける。重なっていた時だけ、押し戻す量を測るために √ を引く。
重なり判定(√なし): dx² + dy² < (r1 + r2)²
押し戻し量(重なった時だけ): overlap = (r1 + r2) − √(dx² + dy²)
平方根は四則演算より高くつく。判定が毎フレーム全ペアぶん走ると、その差が効いてくる。比較は二乗のまま済ませ、実際の距離が要る時だけ平方根を取る、という分け方が衝突コードの定番の節約になる。
円を二つだけ置く。左から流してきた一つが、真ん中で止まっている相手にぶつかる。重なったら、中心を結ぶ線の上で互いを半分ずつ離す。
d2 < rr*rr が重なりの判定で、ここを越えた時だけ √ を引く。overlap がめり込んだ量、nx, ny が二つの中心を結ぶ向き(法線)。押し戻しはこの線の上で起き、overlap / 2 で半分ずつ返すので、ぶつかった相手が静止していても二つとも同じだけ動いて離れる。質量が等しい場合の振る舞いになる。overlap / 2 の比を変えると、軽い方が多く動くようにできる。
これを n 個に増やして、全ペアを総当たりで見る。壁反射も足して、箱の中に閉じ込める。
判定の中身は一対のときと同じで、i < j の二重ループで全ペアを一度ずつ見ている。ぶつかった瞬間だけ円を濃く塗るので、どのペアが接触したかが点滅で出る。
押し戻しているのは位置だけで、速度には触っていない。それでも玉どうしがぶつかると散っていくのは、押し戻しで位置が変わった次のフレームに、速度が前の向きのまま進むため。運動量を正しく保つには法線方向の速度を交換する必要があるが、位置補正だけでも跳ね返りらしき動きは出る。
総当たりで全ペアを見ているので、円が増えると判定回数は二乗で膨らむ。n を 14 から 100 に上げると重くなる。