2Dゲームの当たり判定
文章:syun
日付:2005/8/11
目次
1.はじめに
2.円の場合
3.矩形の場合
4.補足
5.参考
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がある場合、
かつ、
「当たり」
となります。
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.参考
ゲーム開発のための数学・物理学入門
いろいろなあたり判定