キャラクタ同士の衝突を調べるには?(当たり判定2)

考え方

一般的に2Dのゲームでキャラクタ同士の当たり判定を検出する場合、長方形が用いられる。では、2つの長方形の重なり(衝突)のパターンにはどのようなものがあるだろうか。

これらのパターンをそれぞれ調べていたのでは面倒なので、上記3パターンを満たす簡単な判定方法を紹介する。

何度も説明しているが、キャラクタの位置情報は4つの頂点情報のX,Yで管理している。つまり、頂点情報のX,Y座標はそのまま長方形と考えられる。それを使って、当たり判定を行うプログラムを考える。

例えばキャラクタAの頂点情報がa、キャラクタBの頂点情報がbである場合、次のようなif文になる。

if ( a[0].x <= b[2].x && a[0].y <= b[2].y && a[2].x >= b[0].x && a[2].y >= b[0].y )

実際のプログラム

では実際に、2つのキャラクタのあたり判定を行うようプログラムを修正する。

当たり判定処理関数の作成

当たり判定処理はいろんなところで使うことが想像されるので、関数化しておく。プロトタイプ宣言も行うこと。

//-----------------------------------------------------------------------------
// 関数名 : HitCheck()
// 機能概要: あたり判定関数
//-----------------------------------------------------------------------------
bool HitCheck(LPTLVERTEX v1, LPTLVERTEX v2)
{
    if ( v1[0].x <= v2[2].x && v1[0].y <= v2[2].y && v1[2].x >= v2[0].x && v1[2].y >= v2[0].y )
        return true;
    else
        return false;

}

《POINT》

当たり判定処理関数の呼び出し

この関数を使って、2つのキャラクタの衝突を調べてみる。例えば、衝突したらキャラクタ1が元の位置に戻るようにプログラムすると、次のようになる。

//-----------------------------------------------------------------------------
// 関数名 : StartFrame()
// 機能概要: スタート画面処理
//-----------------------------------------------------------------------------
void StartFrame(void)
{
    float mx, my;

    /* 描画処理 */
    // キャラクタ1を描画
    gl_lpD3ddev->SetTexture(0, gl_Texture1);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, VertexDataTbl1, sizeof(TLVERTX));
    // キャラクタ2を描画
    gl_lpD3ddev->SetTexture(0, gl_Texture2);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, VertexDataTbl2, sizeof(TLVERTX));

    /* 移動処理 */
    mx = my = 0.0f;
    if ( gl_KeyTbl[VK_LEFT] & 0x80 )  mx = -2.0f;
    if ( gl_KeyTbl[VK_UP] & 0x80 )    my = -2.0f;
    if ( gl_KeyTbl[VK_RIGHT] & 0x80 ) mx =  2.0f;
    if ( gl_KeyTbl[VK_DOWN] & 0x80 )  my =  2.0f;
    Move(VertexDataTbl1, mx, my);

    /* 指定範囲を超えないようにする */
    MoveCheck(gl_rcMove, VertexDataTbl1);

    /* 当たり判定 */
    if ( HitCheck(VertexDataTbl1, VertexDataTbl2) )
        InitVertex(VertexDataTbl1, 100.0f, 100.0f, 164.0f, 164.0f, 255);

    // リターンキーが押されたら、ゲーム開始
    if ( gl_KeyTbl[VK_RETURN] & 0x80) g_FrameNo = GAME_INIT;

}

《POINT》

※上記修正を行い、2つのキャラクタが衝突したら、キャラクタ1が元の場所に戻ることを確認する。


BACK(画面からはみ出さないようにするには?) NEXT(当たり判定を小さくするには?)