2次元での回転有りの長方形同士の当たり判定 前回やった文字表示で当たったかどうかの状態を表示します 今回使うファイルは次のようになってます。どぞー(-ω-)つ旦 zipでほしい人はこちら 今回焦点を当てたい当たり判定関数はsprite.hとsprite.cppに実装してあります #pragma once // Direct3Dの各種ヘッダーのインクルードが必要なため // すでにまとめてあるヘッダーをインクルードする #include "direct3d.h" struct AnimationNum{ unsigned int numU; unsigned int numV; }; // スプライトクラス(2D板ポリゴン) class Sprite { public: // 板ポリゴン頂点情報 struct Vertex{ float x,y,z;// 3次元座標 float rhw; // 2D変換済みフラグ float u,v; // UV座標 }; // FVF(柔軟な頂点構造体宣言)フラグ static const DWORD SPRITE_FVF = D3DFVF_XYZRHW | D3DFVF_TEX1; // スプライト位置 D3DXVECTOR2 pos; // スプライトサイズ int width; int height; // UVの分割数 unsigned int divU; unsigned int divV; // UVの番号 unsigned int numU; unsigned int numV; // 回転値(ラジアン) float rotate; // コンストラクタ Sprite(); // デストラクタ ~Sprite(); void SetPos(float x,float y); void SetWidth(int Width,int Height); void SetRotate(float Rotate); /////////////////////////////////////////////////////////////////////// void UpdatePos(float x,float y); void UpdateRotate(float Rotate); /////////////////////////////////////////////////////////////////////// void SetDivide(unsigned int DivU,unsigned int DivV); void SetUVNum(unsigned int NumU,unsigned int NumV); void Draw(IDirect3DDevice9* pDevice3D,IDirect3DTexture9* pTexture,bool isTurn = false); }; /////////////////////////////////////////////////////////////////////// // スプライトの当たり判定(2次元のOBB vs OBB) bool IsHitTest(const Sprite& sprite1,const Sprite& sprite2); sprite.cppは次のようになります #include "sprite.h" // 20回と同じなので略 //////////////////////////////////////////////////////////////////////////////////////////// void Sprite::UpdatePos(float x,float y) { pos.x += x; pos.y += y; } void Sprite::UpdateRotate(float Rotate) { rotate += Rotate; } //////////////////////////////////////////////////////////////////////////////////////////// // 20回と同じなので略 //////////////////////////////////////////////////////////////////////////////////////////// // 有向境界ボックス(2次元) struct OBB { D3DXVECTOR2 Pos; // 位置 D3DXVECTOR2 Dir[2]; // XY各座標軸の傾きを表す方向ベクトル float Length[2]; // 各軸方向の長さの半分 }; // OBB作成 void CreateOBB(OBB* pOutOBB,const D3DXVECTOR2& Pos,const D3DXMATRIX& RotateMtx,const D3DXVECTOR2& Length) { pOutOBB->Pos = Pos; pOutOBB->Length[0] = Length.x; pOutOBB->Length[1] = Length.y; pOutOBB->Dir[0] = D3DXVECTOR2(RotateMtx._11,RotateMtx._12); pOutOBB->Dir[1] = D3DXVECTOR2(RotateMtx._21,RotateMtx._22); } // 分離軸に投影された軸成分から投影線分長を算出 float LenSegOnSeparateAxis( D3DXVECTOR2 *Sep, D3DXVECTOR2 *e1, D3DXVECTOR2 *e2 ) { // 3つの内積の絶対値の和で投影線分長を計算 // 分離軸Sepは標準化されていること float r1 = fabs(D3DXVec2Dot( Sep, e1 )); float r2 = fabs(D3DXVec2Dot( Sep, e2 )); return r1 + r2; } // OBB vs OBB bool TestOBBOBB(const OBB &obb1,const OBB &obb2) { // 各方向ベクトルの確保 // (N***:標準化方向ベクトル) D3DXVECTOR2 NAe1 = obb1.Dir[0], Ae1 = NAe1 * obb1.Length[0]; D3DXVECTOR2 NAe2 = obb1.Dir[1], Ae2 = NAe2 * obb1.Length[1]; D3DXVECTOR2 NBe1 = obb2.Dir[0], Be1 = NBe1 * obb2.Length[0]; D3DXVECTOR2 NBe2 = obb2.Dir[1], Be2 = NBe2 * obb2.Length[1]; D3DXVECTOR2 Interval = obb1.Pos - obb2.Pos; // 分離軸 : Ae1 float rA = D3DXVec2Length( &Ae1 ); float rB = LenSegOnSeparateAxis( &NAe1, &Be1, &Be2 ); float L = fabs(D3DXVec2Dot( &Interval, &NAe1 )); if( L > rA + rB ) return false; // 衝突していない // 分離軸 : Ae2 rA = D3DXVec2Length( &Ae2 ); rB = LenSegOnSeparateAxis( &NAe2, &Be1, &Be2); L = fabs(D3DXVec2Dot( &Interval, &NAe2 )); if( L > rA + rB ) return false; // 分離軸 : Be1 rA = LenSegOnSeparateAxis( &NBe1, &Ae1, &Ae2); rB = D3DXVec2Length( &Be1 ); L = fabs(D3DXVec2Dot( &Interval, &NBe1 )); if( L > rA + rB ) return false; // 分離軸 : Be2 rA = LenSegOnSeparateAxis( &NBe2, &Ae1, &Ae2); rB = D3DXVec2Length( &Be2 ); L = fabs(D3DXVec2Dot( &Interval, &NBe2 )); if( L > rA + rB ) return false; // 分離平面が存在しないので「衝突している」 return true; } // スプライトの当たり判定(2次元のOBB vs OBB) bool IsHitTest(const Sprite& sprite1,const Sprite& sprite2) { OBB obb1; OBB obb2; D3DXMATRIX rotMtx1; D3DXMATRIX rotMtx2; D3DXMatrixRotationZ(&rotMtx1,sprite1.rotate); D3DXMatrixRotationZ(&rotMtx2,sprite2.rotate); CreateOBB(&obb1,sprite1.pos,rotMtx1,D3DXVECTOR2(sprite1.width/2.0f,sprite1.height/2.0f)); CreateOBB(&obb2,sprite2.pos,rotMtx2,D3DXVECTOR2(sprite2.width/2.0f,sprite2.height/2.0f)); return TestOBBOBB(obb1,obb2); } 実行結果は次のようになります
|