===== DX 2D비행슈팅강좌 ======
===== 17. 충돌박스 =====
충돌검사를 이미지의 크기로만했었는데, 그럴경우
너무 광범위한 판정이 납니다.
충돌박스를 만들어서 이미지와는 별도로 영역을 얻어서
충돌검사를 해보겠습니다.
적의 판정영역이 조금 작아진것을 알수가 있습니다.
1. 구조체 정의
2. 이미지내에 충돌박스를 포함하기
3. 충돌 데이터 설정
4. 충돌데이터 넣기
5. 이동시 충돌박스도 같이 이동
6. 충돌박스 얻기
7. 충돌체크 하기
1. 구조체 정의
struct BoundingBox
{
D3DXVECTOR3 LT;
D3DXVECTOR3 RB;
};
typedef std::vector <BoundingBox*> BoundBoxVec;
충돌박스 구조체를 만듭니다.
2. 이미지내에 충돌박스를 포함하기
struct Image_data
{
LPDIRECT3DTEXTURE9 Texture; // 텍스쳐
RECT Source; // 텍스쳐내 이미지의 좌표
D3DXVECTOR3 Position; // 이미지가 화면에 그려질 좌표
D3DXVECTOR3 Center; // 이미지의 센터
FLOAT Time; // 재생시간, 상대시간
};
struct Image : public Image_data
{
BoundBoxVec BoundBox; // 충돌박스
};
구조체내에 벡터를 넣으면, ZeroMemory사용시 메모리릭이 발생하므로,
구조체 상속을 통해서 "ZeroMemory(&BulletImage, sizeof(Image_data))"
과 같은 형태로 초기화 합니다.
그 이유로 구조체를 상속하여 사용합니다.
3. 충돌 데이터 설정
BoundBoxVec vBound;
BoundingBox* pBox = NULL;
pBox = new BoundingBox;
pBox->Left = -54.0f;
pBox->Right = 43.0f;
pBox->Top = -90.0f;
pBox->Bottom = 104.0f;
vBound.push_back( pBox );
_Enemy.setBoundingBox( &vBound );
충돌 데이터는 벡터를 생성한후, BoundingBox의 인스턴스를
힙메모리로생성하고 값을 정의한후에 벡터에 넣어
_Enemy에게 충돌박스를 설정합니다.
여기에서는 Character에게만 했지만,
각 이미지 마다 적용시, 이미지에 넣기만 하면됩니다.
4. 충돌데이터 넣기
VOID Character::setBoundingBox(const BoundBoxVec* vBox)
{
_vBoundBox = *vBox;
}
벡터는 복사만 하면 끝입니다.
5. 이동시 충돌박스도 같이 이동
iBound_size = _vBoundBox.size();
for (INT c=0; c<iBound_size; ++c )
{
_vBoundBox[c]->LT.x += vPos->x;
_vBoundBox[c]->LT.y += vPos->y;
_vBoundBox[c]->RB.x += vPos->x;
_vBoundBox[c]->RB.y += vPos->y;
}
충돌박스가 따라 다녀야 하므로, Character가이동시
같이 이동합니다.
6. 충돌박스 얻기
BoundBoxVec& Character::getBoundingBox(VOID)
{
if ( _vBoundBox.empty() == FALSE )
{
return _vBoundBox;
}
else
{
return _vImages[_uAni_num][_uImage_num]->BoundBox;
}
}
충돌박스는 각이미지마다 충돌벡터가 있지만, Character안에도 하나 있습니다.
만약, Character에 단 한개의 충돌박스가 있으면, 그것을 리턴합니다.
탄막슈팅처럼, 이미지의 충돌지점은 동일한데, 굳이 이미지마다 충돌박스를
정의할필요가 없을때 사용합니다.
이미지내에 충돌박스가 없는데, 리턴하게 되면, 다운됩니다.
7. 충돌체크 하기
VOID Application::UpdateCollision(VOID)
{
const BoundBoxVec& vEnemyBox = _Enemy.getBoundingBox();
BoundBoxVec& vBulletBox = _Bullet[0].getBoundingBox();
Property proEnemy = *_Enemy.getProperty();
for (INT i=0; i<100; ++i)
{
if ( _Bullet[i].getVisible() == TRUE )
{
BoundBoxVec& vBulletBox = _Bullet[i].getBoundingBox();
for (UINT k=0; k<vEnemyBox.size(); ++k)
{
for (UINT c=0; c<vBulletBox.size(); ++c)
{
if ( vBulletBox[c]->LT.x < vEnemyBox[k]->RB.x
&&vEnemyBox[k]->LT.x < vBulletBox[c]->RB.x
&&vBulletBox[c]->LT.y < vEnemyBox[k]->RB.y
&&vEnemyBox[k]->LT.y < vBulletBox[c]->RB.y)
{
// 충돌한 총알은 안보이고, 게이지 깍기
if ( proEnemy.HP >= .0f )
{
_Bullet[i].setVisible(FALSE);
proEnemy.HP -= _Bullet[i].getProperty()->AttackDamage;
}
}
}
}
}
}
// 적의 능력치 업데이트
_Enemy.setProperty(&proEnemy);
}
사각영역의 충돌방식은 이전과 같습니다.
다만, 그 사각영역을 이미지로 체크하는것이 아니라, 충돌영역으로
판정을 한다는것이 다릅니다.
댓글 영역
획득법
① NFT 발행
작성한 게시물을 NFT로 발행하면 일주일 동안 사용할 수 있습니다. (최초 1회)
② NFT 구매
다른 이용자의 NFT를 구매하면 한 달 동안 사용할 수 있습니다. (구매 시마다 갱신)
사용법
디시콘에서지갑연결시 바로 사용 가능합니다.