ねのぷろ! ~げーむ・ぷろぐらみんぐ・ぶろぐ〜

プログラミングやゲームについてだらだら書きます。https://twitter.com/nenowawon

C++ 衝突判定の中身解説

こんにちは。ネノワヲンです。今日は、昨日作った衝突判定についての中身を書きます。

ソース

コライダー(衝突物クラス)
void RectangleCollider::Create(GameObject* object, ImageVertex(&vertexArray)[4]) {

    Create(object);

    float min_x = 0;
    float max_x = 0;
    float min_y = 0;
    float max_y = 0;
    int size = sizeof(vertexArray) / sizeof(ImageVertex);

    for (size_t i = 0; i < size; i++)
    {
        // x座標の最大値を更新する
        if (vertexArray[i].m_vertPos.x > max_x) {
            max_x = vertexArray[i].m_vertPos.x;
        }

        // x座標の最小値を更新する
        if (vertexArray[i].m_vertPos.x < min_x) {
            min_x = vertexArray[i].m_vertPos.x;
        }

        // y座標の最大値を更新する
        if (vertexArray[i].m_vertPos.y > max_y) {
            max_y = vertexArray[i].m_vertPos.y;
        }

        // y座標の最小値を更新する
        if (vertexArray[i].m_vertPos.y < min_y) {
            min_y = vertexArray[i].m_vertPos.y;
        }
    }
    // 左辺の座標を設定
    m_pRect->left = min_x;
    // 右辺の座標を設定
    m_pRect->right = max_x;
    // 上辺の座標を設定
    m_pRect->top = max_y;
    // 下辺の座標を設定
    m_pRect->bottom = min_y;
}

void RectangleCollider::Create(GameObject* object) {
    m_pGameObject = object;
    m_pRect = new RectangleVertex();
    DirectXRenderer::instance->AddCollider(this);
}

bool RectangleCollider::CheckCollider(RectangleCollider * collider)
{
    // チェック相手のコライダー    
    RectangleVertex checkRect = collider->GetRect();
    // 自分のコライダー
    RectangleVertex myRect = GetRect();

    //横に重なっていた場合
    if (myRect.left <= checkRect.right && myRect.right >= checkRect.left)
    {
        //縦に重なっていた場合
        if (myRect.top >= checkRect.bottom && myRect.bottom <= checkRect.top)
        {
            return true;
        }
    }
    return false;
}

RectangleVertex RectangleCollider::GetRect()
{
    RectangleVertex rect = RectangleVertex();

    // 頂点座標をワールド座標に変換する
    // 左
    rect.left = (m_pGameObject->m_transform->m_pos.x) + (m_pRect->left);
    // 上
    rect.top = (m_pGameObject->m_transform->m_pos.y) + (m_pRect->top);
    // 右
    rect.right = (m_pGameObject->m_transform->m_pos.x) + (m_pRect->right);
    // 下
    rect.bottom = (m_pGameObject->m_transform->m_pos.y) + (m_pRect->bottom);

    return rect;
}

このクラスは、4辺の座標、自分のオブジェクトをメンバ変数として保持しています。 コライダーを受け取り、衝突しているかどうかを判定し、結果としてboolを返します。

オブジェクトクラス(コライダーに命令を送る)
HRESULT SpriteTest::Create(HWND hwnd)
{
    HRESULT hr;

    // 画像を描画するクラスを作成する
    m_pSprite = new Mesh::Sprite();
    hr = m_pSprite->Create(hwnd, &IMAGE_FILE_NAME);

    // コライダーを作成する
    m_pCollider = new RectangleCollider();
    m_pCollider->Create(this, m_pSprite->m_pVertexArray);

    // タグを設定する
    m_tag = Tag::TEST;

    return hr;
}

void SpriteTest::LateUpdate()
{
    // コライダーのリストを取得
    for (auto collider : DirectXRenderer::instance->m_ColliderList) {
        
        // プレイヤーとのみ衝突する
        if (collider->m_pGameObject->m_tag != Tag::PLAYER) { continue; }

        // 衝突判定をする
        if (!m_pCollider->CheckCollider(collider)) { continue; }

        // 右に移動(テスト用)
        MoveX(0.05f);
    }
}

メインクラスに保持してあるコライダーを取得し、自分のコライダーに命令を送ります。 衝突している場合、右に移動しています。 また、オブジェクトごとのタグによりプレイヤーを認識しています。

あとがき

このブログとしては初の、ソースについての解説になりました。実際に何をしているかの説明は難しいですね・・・! 何度も練習して上達したいと思います。