フォートナイトみたいなオンラインバトロワゲームを作っています。優秀なサンプルコードから作成を開始したので早い段階で一応形にはなりました。しかし、サンプルをいじりすぎて接触判定に矛盾が生じてきてしまいました。
・グラフィック上は弾が当たっているのにダメージがない。
・建築して壁を立てているのに弾丸がすり抜けてくる。
Rayを飛ばしてぶつかるポリゴンを探すというのが一般的な手法のようですが、軽い処理でゲーム内に自由に組み込みたいので接触判定の部分を自作してみました。以下、その説明です。(数式等を使用しますが、厳密な数学的表現ではありませんがご了承ください)
接触判定方法:3次元空間での平面と線分の交点を求める
現在の建築の種類は「壁、床、階段」のみなので、建築は全て1平面で表現できます。また、プレイヤーも複数(3〜6)の平面で簡易的に表現することができます。
弾丸は現在のゲーム仕様では速度のある表現となっているので線分で表すことができます。従って、弾が建築(またはプレイヤー)に当たったかどうかは
平面と線分の交点を求め、交点が平面の範囲内(建築の大きさ)にあるかどうかを求める
事で判別できそうです。
ベクトル、行列表記だと次のようになります。
(添字が小文字でない、その他色々、簡易的な数学表現です。お許しを)
上図にて、矢印のない太字は一座表です。
壁の位置と大きさから、P0, u, vが決まります。
弾丸の位置と進行方向から、b, dが決まります。
行列[A]は3x3です。逆行列は公式があるので{s,t,e}は一発で求まります。
det[A]が0の場合は弾丸の進行方向が壁と並行なので交点がないという事になります。実際のコードではある程度小さな値ならほぼ並行という事で交点なしとします。
det[A]が0でなく{s,t,e}が得られた場合は、その値を場合分して交点が壁の範囲(s, tが0以上、1以下)にあるかを調べます。弾丸が速度を持っている仕様なので1フレームで進む距離を弾丸の長さ(L)と考え、eは0以上、L以下であるかを調べます。
条件を満たしていたら「被弾」の処理をします。
s,tが得られると被弾場所も求めることができます。
以上、弾丸と壁の接触判定の記事でした。