★敵キャラクター 衝突判定(円)の改良★


今回は「円」の衝突判定の見直しを行います。

現在の判定関数は下のようになっています。

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関数」を使う事無く同じ判定を行うプログラムが完成しましたので、実行して確認してください。。


次回は「矩形(四角形)」の衝突判定を説明します。


次へ

戻る

目次へ