当たり判定処理 前編

2012 年 5 月 21 日 by 山平

ゲームに欠かせない処理に当たり判定があります。
当たり判定は大きく分けて「プレイヤーキャラクタと敵キャラクタ(動くもの同士)の当たり判定」と「キャラクタと壁(動くものと動かないもの)の当たり判定」の2通りあります。

当たっているかどうかを調べると言う意味ではどちらも同じなのですが、当たった後の処理に違いがあります。
キャラクタ同士の場合、何と何が当たったかで処理が変わるため、処理(仕様)を決めておく必要があります。
キャラクタと壁の場合、当たった後の処理で座標を修正するのはキャラクタなのであまり難しく考える必要がありません。

前編ではキャラクタ同士の当たり判定について考えてみます。

スプライトを使う際の前提

スプライトは一定のサイズ(32×32など)の画像を複数枚切り替えてアニメーションを実現します。
画像は何かしらのキャラクタを描くのが普通ですので、スプライトのサイズよりも小さいサイズで当たり判定を行う必要があります。
言葉で説明すると分かりにくいですが、絵で見ればわかりやすいと思います。

hitting

青い四角がスプライト画像全体のサイズ(32×32)、黄色い四角が実際のキャラクタサイズに合わせた当たり判定のサイズです。
クマの背中側の隙間が大きいように見えますが、計算を簡単にするために左右のオフセットを1つの値で保持するためです。

当たり判定の考え方

先の図の黄色い四角同士が少しでも重なっている場合、当たっていると判断できます。
しかし、キャラクタごとに黄色い四角の大きさは異なることもあり、場合によってはスプライトのサイズそのものの大きさも異なることもあります。
なるべく簡単に、汎用的に判定する方法で済ませたいものです。

先の図の黄色い四角の左上、右下の赤い点に注目します。
茶クマの左上点が白クマの右下点より左上、かつ茶クマの右下点が白クマの左上点より右下のとき、茶クマと白クマは当たっています。
式にすると以下のようになります。

//BB: 茶クマ, WB: 白クマ
//左上点: lx, uy, 右下点: rx, by
(BB.lx < WB.rx) && (BB.rx > WB.lx) && (BB.uy < WB.by) && (BB.by > WB.uy)

細かい説明は省きますが、大きさの異なる四角同士でもこの式一発で判定できます。

enchant.jsの場合

enchant.jsの場合、スプライト同士の当たり判定のメソッドがあらかじめ準備されています。
実際にはEntityオブジェクトに実装されているので、画面上全てのオブジェクト同士で当たり判定を行うことができます。

enchant.Entity#intersect

しかしこの処理はスプライト(その他オブジェクト)そのものの大きさでしか判定できません。
なので上で示した式の前の事前処理としてざっくりと当たっているかどうかを調べるために使える程度です。

if(BB.intersect(WB)){
return (BB.lx < WB.rx) && (BB.rx > WB.lx) && (BB.uy < WB.by) && (BB.by > WB.uy);
}else{
return false;
}

実際の処理の場合

実際にゲームに当たり判定を実装する場合、全てのキャラクタが全てのキャラクタと当たっているか判定するとキャラクタ数の2乗(引くキャラクタ数)回の判定を行うことになります。
これでは無駄なので、キャラクタの種類ごとに何と判定するか、当たった場合にどうするかということを分けておきます。

プレイヤー
当たり判定する相手:敵キャラクタ、敵キャラクタの攻撃(剣、弾など)
当たったときの処理:ダメージを受ける
敵キャラクタ
当たり判定する相手:プレイヤーの攻撃(剣、弾など)
当たったときの処理:ダメージを受ける

タグ: ,

TrackBack