WCE blog

早稲田大学公認 総合デジタル創作サークル 早稲田コンピュータエンタテインメント

当たり判定と距離関数【2022年WCE新歓ブログ 第2回】

皆さん、ゲーム作ってますか??WCENYLONです。

ゲームを作る上で当たり判定は本当によく使います。いいライブラリだとデフォルトであるのですが、僕が使っているエンジンには当たり判定の関数がないため、毎回手作りで距離関数を作っています。今回はその距離関数について説明していきます。

距離関数とは

距離関数とは空間内の2点を引数に持つ実関数です。平たく言うと2つの点で決まる長さです。まっすぐ直線距離を測る以外にも長さを決めることはできて、距離関数の定義さえ満たせていれば様々な測り方ができます。

距離関数の定義

関数 d距離関数であるとき、

(1) 任意の2点 p,q について d(p,q)\geq 0 である。(非負性:どんな長さも0以上の値である)

(2) d(p,q)= 0 のとき p=q であり、 p=q のとき d(p,q)= 0 である。(同一律:長さが0なら同じ点で、同じ点同士のの長さは0)

(3)任意の3点 p,q について d(p,q)=d(q,p) である。(対称律:p から q の長さと q から p の長さは等しい)

(4)任意の3点 p,q,r について d(p,q)\leq d(p,r)+d(r,q) である。(三角不等式:p から r を経由した q までの長さは q から p の長さより長い)

の4つを満たす。

距離関数の例

上の定義を満たしてるものは何でも距離関数になります。以下では二次元空間上の直交座標を用いた距離関数を考えます。2点A,BA=(a.x,a.y),B=(b.x,b.y)として進めます。

ユークリッドノルムd(A,B)=\sqrt{(a.x-b.x)^{2}+(a.y-b.y)^{2}}f:id:WCE:20220409163514p:plain

一番有名な直線的な距離関数。 三平方の定理ですね。

マンハッタンノルムd(A,B)=|a.x-b.x|+|a.y-b.y|f:id:WCE:20220409163519p:plain

縦と横を別々に測って足した長さを返す距離関数。斜めには直線的に測れません。

チェビシェフノルムd(A,B)=\max(|a.x-b.x|,|a.y-b.y|)f:id:WCE:20220409163625p:plain

縦と横を別々に測って大きい方を返す距離関数。意外と便利。

距離関数と当たり判定

実際に距離関数をゲーム内で使うとどうなるのでしょうか。ゲームでよく使う当たり判定の処理を見ていきましょう。

function dist(a,b)
 return max(abs(a.x-b.x),abs(a.y-b.y))
end
……
--plはプレイヤーでeは敵です。
 if dist(pl,e)<8 then
  pl_damage()
 end

このように敵とプレイヤーの距離がチェビシェフノルムで十分近いときダメージが入るようにできました! ユークリッドノルムでもいいのですがキャラクターの形状や平方根の処理がない手軽さを考えるとチェビシェフノルムやマンハッタンノルムなどの方がいいときもあります。もっと複雑な関数で距離関数を作れば複雑な形状のキャラクターの当たり判定も実装できますよ!神!