★敵キャラクター 衝突判定(矩形)★


まず「矩形(くけい)」とは四角形の事です。

「円」の衝突判定は比較的簡単なため、色々な場面で使用されますが「円」だけでは対処出来ない事も多くあります。

例えば四角い物体同士の衝突判定を「円」で行うと、

この状態でも2つの物体は衝突していない事になります。

また長細い物体の衝突判定を「円」で行うと、

複数の「円」が必要になります。


考え方


では「矩形」の衝突判定はどのように考えればよいでしょうか。

衝突している状態と、衝突していない状態を図にしてみます。

1と3は衝突しておらず、2と4は衝突してる状態です。


注目して欲しいのは辺の状態です。

とりあえず、左右方向だけを考え注目して欲しい辺の色を変えてみます。

1と2は「物体Aの右辺」と「物体Bの左辺」に注目しました。

3と4は「物体Aの左辺」と「物体Bの右辺」に注目しています。

これを見て考えると、

 「物体Aの右辺」が「物体Bの左辺」より「右にある」時

 「物体Aの左辺」が「物体Bの右辺」より「左にある」時

2つの物体は衝突している、と判断出来そうです。


ただし、これは左右方向だけですから、同じことを上下方向でも考えなければなりません。

上下方向を考えると、

 「物体Aの底辺」が「物体Bの上辺」より「下にある」時

 「物体Aの上辺」が「物体Bの底辺」より「上にある」時

2つの物体は衝突している、と判断出来ます。

左右と上下の条件が全て整った時に、2つの物体は衝突しています。


プログラムにするため言葉を座標に置き換えてみましょう。

現在のプログラムで使っている情報は「転送先XY座標」と「幅」「高さ」です。

 「物体Aの右辺」が「物体Bの左辺」より「右にある」時

 「物体AのX座標+幅」が「物体BのX座標」より「大きい」時

と書き換える事が出来ます。

クライアント領域の座標の原点は左上ですから「右にある」と言うのは、座標として「大きい」と言う事です。

残りの3つも変えてみます。

 「物体Aの左辺」が「物体Bの右辺」より「左にある」時

 「物体AのX座標」が「物体BのX座標+幅」より「小さい」時

となり、

 「物体Aの底辺」が「物体Bの上辺」より「下にある」時

 「物体AのY座標+高さ」が「物体BのY座標」より「大きい」時

となり、

 「物体Aの上辺」が「物体Bの底辺」より「上にある」時

 「物体AのY座標」が「物体BのY座標+高さ」より「小さい」時

となります。


この4つの条件、

 「物体AのX座標+幅」が「物体BのX座標」より「大きい」時

 「物体AのX座標」が「物体BのX座標+幅」より「小さい」時

 「物体AのY座標+高さ」が「物体BのY座標」より「大きい」時

 「物体AのY座標」が「物体BのY座標+高さ」より「小さい」時

が、全て成り立つ時、2つの物体は衝突したと言う事になります。


実装


それでは「Base.h」を開き、関数のプロトタイプ宣言を追加しましょう。

class Base {
public:

    Base(const int width, const int height);

    bool CollideCircle(const Base &refTarget);

    bool CollideBox(const Base &refTarget);

    void Delete();

「Base.cpp」を開き、「CollideCircle関数」の下に実体を追加します。

bool Base::CollideBox(const Base &refTarget)
{
    if (!m_bExist) {
        return false;
    }

    if (!refTarget.m_bExist) {
        return false;
    }

    if (m_x + WIDTH > refTarget.m_x
        && m_x < refTarget.m_x + refTarget.WIDTH
        && m_y + HEIGHT > refTarget.m_y
        && m_y < refTarget.m_y + refTarget.HEIGHT) {

        return true;
    }

    return false;
}

上に書いてある4つの条件と見比べてください。


次に「SceneGame.cpp」の「Update関数」の衝突判定関数を差し替えてください。

void SceneGame::Update()
{
    if (m_shot.CollideBox(m_enemy)) {
        m_enemy.Delete();
        m_shot.Delete();
    }

    m_player.Update(m_pEngine, m_shot);

    m_shot.Update();

    m_enemy.Update();
}

それでは実行してみましょう。

ちゃんと「弾」が当たって「敵」が消えれば成功です。


「円」と同じように、判定の範囲を狭める事も出来ますが説明は省略します。

要は判定に使う「矩形」を小さくすれば良いだけです。


「円」と「矩形」2つの衝突判定方法を説明しましたが、単純なゲームであればこの2つの方法である程度はカバー出来ると思います。

その他の判定については、別の項目で説明したいと思います。


次へ

戻る

目次へ