今回は「円」の衝突判定の見直しを行います。
現在の判定関数は下のようになっています。
bool Base::CollideCircle(const Base &refTarget) { if (!m_bExist) { return false; } if (!refTarget.m_bExist) { return false; } int myRadius = WIDTH / 2; int targetRadius = refTarget.WIDTH / 2; int myCenterX = m_x + myRadius; int myCenterY = m_y + myRadius; int targetCenterX = refTarget.m_x + targetRadius; int targetCenterY = refTarget.m_y + targetRadius; int x = myCenterX - targetCenterX; int y = myCenterY - targetCenterY; double distance = sqrt(x * x + y * y); int totalRadius = myRadius + targetRadius; totalRadius = static_cast<int>(totalRadius * 0.8); if (distance <= totalRadius) { return true; } return false; } |
「改良」と言うからには「問題点」があるはずです。
その「問題点」は↓の部分です。
double distance = sqrt(x * x + y * y); |
この部分は「三平方の定理」を使って斜辺の長さを求めています。
斜辺は2つの物体の中心から中心の距離を表しており、判定に必要な情報です。
しかし、平方根を求めるために使っている「sqrt関数」は複雑な計算で成り立っているため、(少し)計算に時間がかかるのです。
※「sqrt」は「Square Root(平方根)」の略です。
今回のように「敵」が1体しかいなければ何の問題にもなりません。
しかし「弾幕シューティングゲーム」のように、多くの「弾」や「敵」と判定を行う場合、その「少し」の時間が問題になってくるのです。
そこで「sqrt関数」を使わない方法に変更してみます。
平方根を計算しないように
double distance = sqrt(x * x + y * y); |
の部分を↓のように変更します。
int distance = x * x + y * y;
|
平方根を求めず、Xの2乗とYの2乗を加算したままの数値を使用します。
変数「distance」も「int型」に変更しました。
これに対して「半径の合計」も2乗します。
totalRadius = static_cast<int>(totalRadius * 0.8);
totalRadius *= totalRadius;
if (distance <= totalRadius) {
return true;
}
|
平方根を求めなくても2乗した値同士を比較すれば問題ありません。
これで「sqrt関数」を使う事無く同じ判定を行うプログラムが完成しましたので、実行して確認してください。。
次回は「矩形(四角形)」の衝突判定を説明します。