2Dゲームの当たり判定
文章:syun
日付:2005/8/11

目次
1.はじめに
2.円の場合
3.矩形の場合
4.補足
5.参考






1.はじめに
今回は、当たり判定の作りかたを解説します。

とりあえず、2Dゲームで当たり判定を作る場合は、
  1. 矩形
という2つのパターンがあります。

他にも地形との当たり判定に、直線を使うことがありますが、
私自身が使ったことがないため、ここでは解説しません。
(というかできません(笑)

まあ、とりあえず、この2つを抑えておけば、
ほとんどの2Dゲームの当たり判定はOKです(たぶん)




2.円の場合
当たり判定に円の場合を使うメリットは、とにかく「簡単」です。

必要な情報量や処理がとっても単純明快となるからです。

やり方を図に描くと、こんな感じです。
境界円

まず、準備として、
当たり判定を行いたいオブジェクト(ここでは「スプライト」と定義します)に、
以下の情報を持たせます。
この情報を使って、当たり判定を行います。

方法としては、、、比較するスプライトを、例えばAとBとします。

そして、スプライトAとスプライトBとの を算出します。
(図での赤線の長さ)

具体的な数値を出してみます。

例えば、Aの中心座標は(20,50)で、Bの中心座標は(120,30)とします。

そうするとピタゴラスの定理により、

中心間の距離算出1

中心間の距離算出2

中心間の距離算出3

となり、「102」が2点間の距離となります。

そして、
Aの半径を30、Bの半径を40とします。

その場合、30+40=70で2点間の距離が「70」より近かった場合に、 となります。 (よって、この場合は「当たり」ではありません)

「本当にそんなんでできるんかよ!」

と思われる方は、紙に書いて計算してもらうと、納得できると思います。


また、√の計算は結構重いので使用せずに、

中心間の距離算出4

(rは半径)

とすると処理の高速化が望めます。




3.矩形の場合
「矩形」とは、四角形のことです。

矩形を使うメリットとしては、 ということがあげられます。

例えば、円の場合には、長細いスプライトの場合に
当たり判定からはみ出してしまい、よろしくありません。

また、矩形は円のように乗算を行わず、大小比較だけなので、判定処理が速いです。
(マシン語には乗算がないため、その分乗算は処理が重いのです)

弾幕シューティングのように、多くのスプライト同士を比較するときには、
矩形を使ったほうが処理的に有利ですね。


ただ、やり方は、円に比べると若干ややこしいかもしれません。
境界矩形

まず準備として、以下の情報を保持しておきます。
そして判定は、以下の条件により行います。
例えば、スプライトAとスプライトBがある場合、 かつ、 「当たり」

となります。

C言語風にRECT構造体を使うとこんな感じです。
  RECT a;
  RECT b;
  if((a.left < b.right)
    && (a.right > b.left)
    && (a.top < b.bottom)
    && (a.bottom > b.top))
  {
    // 当たり
  }
デメリットとして、円と比べると問題点があります。

それは ということです。

円はどれだけ回転しても、半径は変わりませんが、
矩形の場合は、回転すると、この処理が使えなくなります。

これを解決するためには、
1つのスプライトに複数の当たり判定の矩形をくっつけてやります。

そして、スプライトが回転する場合には、
矩形も回転させるようにすると、正確な当たり判定が可能となります。
(複数の円をくっつけてやる方法もアリですね)




4.補足
・補足1

冒頭でも言及しましたが、斜面など、地形との衝突判定は、
「直線と直線との交差判定」により行う方法があります。

これについては、使ったことがないため、
私が実際に使ってみた後で解説したいと思っています(´▽`;

・補足2

複雑な形状である場合、
円や矩形を複数組み合わせて当たり判定を作ります。

その場合には、当たり判定を描画する処理を作って、
目で確認できるようにすると、デバッグがやりやすくなります。

・補足3
円であっても矩形であっても、スプライトが「アニメーション」する場合は、
それにより、当たり判定の大きさが変わりまくるので、
処理を作るのが死ぬほど大変になります。

そこで、そんな悲惨なゲーム(笑)を作ることになった場合は、
当たり判定エディタを作ることをオススメします。
例えば、こんな感じです。
当たり判定エディタ




5.参考
ゲーム開発のための数学・物理学入門
いろいろなあたり判定