2Dゲームの当たり判定

投稿者: | 2012年5月22日

1.はじめに

今回は、当たり判定の作りかたを解説します。

とりあえず、2Dゲームで当たり判定を作る場合は、

  • 矩形

という2つの簡単なパターンがあります。

他にも地形との当たり判定(特に斜めの地形判定)に直線を使うことがありますが、まあ、とりあえず、この2つを抑えておけば、ほとんどの2Dゲームの当たり判定はOKです

2.円の場合

当たり判定に円の場合を使うメリットは、とにかく「簡単」です。必要な情報量や処理がとっても単純明快となるからです。

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

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

  • 中心座標
  • 円の半径

この情報を使って、当たり判定を行います。方法としては、、、比較するスプライトを、例えばAとBとします。

そして、スプライトAとスプライトBとの

  • 中心座標間の距離

を算出します。(図での赤線の長さ)

具体的な数値を出してみます。例えば、Aの中心座標は(20,50)で、Bの中心座標は(120,30)とします。そうするとピタゴラスの定理により、

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

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

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

(rは半径)

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

3.矩形の場合

「矩形」とは、四角形のことです。

矩形を使うメリットとしては、

  • スプライトが細長くても大丈夫
  • 円より処理が速い

ということがあげられます。

例えば、円の場合には、長細いスプライトの場合に当たり判定からはみ出してしまい、よろしくありません。また、矩形は円のように乗算を行わず、大小比較だけなので、判定処理が速いです。(マシン語には乗算がないため、その分乗算は処理が重いのです)

弾幕シューティングのように、多くのスプライト同士を比較するときには、矩形を使ったほうが処理的に有利ですね。ただ、やり方は、円に比べると若干ややこしいかもしれません。

まず準備として、以下の情報を保持しておきます。

  • スプライトの左上の座標(Pとします)
  • スプライトの右下の座標(Qとします)

そして判定は、以下の条件により行います。 例えば、スプライトAとスプライトBがある場合、AのPがBのQより左上にあり、かつ、AのQがBのPより右下にある場合、「当たり」となります。

C言語風にRECT構造体を使うとこんな感じです。

  RECT a;
  RECT b;
  if((a.left < b.right)
    && (a.right > b.left)
    && (a.top < b.bottom)
    && (a.bottom > b.top))
  {
    // 当たり
  }

デメリットとして、円と比べると問題点があります。それは「スプライトが回転したら使えない」ということです。円はどれだけ回転しても、半径は変わりませんが、矩形の場合は、回転すると、この処理が使えなくなります。

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