GAME
当たり判定いろいろ


HomeProgramming TipsGame Tips[GAME003]

ゲームでは当たり判定が重要な処理となります。
また、一般アプリでも実は当たり判定はマウスを使用している以上、意外と頻繁に必要です。
様々な当たり判定を列挙してみました。


四角と四角の当たり判定


RECT と RECT が重なっているか判定します。
バウンディングボックスの判定と呼ばれています。

自分で if 判定しても良いのですが、これらは便利な関数が用意されています。
MFC では、CRect のメソッドを使います。SDK では、同名の API があります。
下記のコードは説明のため関数として紹介していくすが関数化は不要ですね ^-^;

■ MFC

inline BOOL IsHitRect(CRect& rc1, CRest& rc2)
{
    CRect rcResult;
    return rcResult.IntersectRect(&rc1, &rc2);
}



■ SDK

inline BOOL IsHitRect(RECT& rc1, RECT& rc2)
{
    RECT rcResult;
    return ::IntersectRect(&rcResult, &rc1, &rc2);
}




四角と点(ポイント)の当たり判定


RECT 内に POINT が含まれているか判定します。
マウスカーソルが範囲指定内にあるかの判定でよく使用されます。

■ MFC

inline BOOL IsHitPoint(CRect& rc, CPoint& pt)
{
    return rc.PtInRect(pt);
}



■ SDK

inline BOOL IsHitPoint(RECT& rc, POINT& pt)
{
    return ::PtInRect(&rc, pt);
}




円と円の当たり判定


円と円が衝突しているか判定します。
三角形の定理により2点間の距離を求め各円の半径の合計より短いかどうかで判定します。
特にシューティングゲームでは多用すると良いでしょう。
本来はベクトルクラスを使うと良い判定です。

なお、円と点(ポイント)の判定は点の半径を 1.0f とすればよいです。

※ 下記判定は「食い込み」です。
※ 判定を「<」から「<=」に変えると接触も当たりと見なします。

■ DirectX

#include <d3dx8math.h>
inline BOOL IsHitCircle(
    D3DXVECTOR2 vec2Pos1, float fRad1,  // 円1の中心位置と半径
    D3DXVECTOR2 vec2Pos2, float fRad2   // 円2の中心位置と半径
)
{
    D3DXVECTOR2 vec2Dif = vec2Pos2 - vec2Pos1;
    float fLength = fRad1 + fRad2;
    return D3DXVec2LengthSq(&vec2Dif) < fLength * fLength;
}



ちなみに DirectX なら 3D 空間でも簡単です。


inline BOOL IsHitBall(
    D3DXVECTOR3 vec3Pos1, float fRad1,  // 球1の中心位置と半径
    D3DXVECTOR3 vec3Pos2, float fRad2   // 球2の中心位置と半径
)
{
    D3DXVECTOR3 vec3Dif = vec3Pos2 - vec3Pos1;
    float fLength = fRad1 + fRad2;
    return D3DXVec3LengthSq(&vec3Dif) < fLength * fLength;
}



■ MFC

inline BOOL IsHitCircle(
    CPoint& pt1, float fRad1,   // 円1の中心位置と半径
    CPoint& pt2, float fRad2    // 円2の中心位置と半径
)
{
    CPoint pt = pt2 - pt1;
    float fLength = fRad1 + fRad2;
    return float(pt.x * pt.x + pt.y * pt.y) < fLength * fLength;
}



■ SDK

inline BOOL IsHitCircle(
    POINT& pt1, float fRad1,    // 円1の中心位置と半径
    POINT& pt2, float fRad2     // 円2の中心位置と半径
)
{
    float fDifX = float(pt2.x - pt1.x);
    float fDifY = float(pt2.y - pt1.y);
    float fLength = fRad1 + fRad2;
    return fDifX * fDifX + fDifY * fDifY < fLength * fLength;
}






 Copyright 2005 VALGUS. All Rights Reserved.