*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처
hyrule.tistory.com
[사전 지식]
#ifdef _DEBUG
//...코드...//
#endif
- #이 사용됨 -> 전처리기
- #ifdef 뒤의 문구가 #define으로 정의되어 있으면, 밑에 있는 코드부터 #endif 전까지를 컴파일 할 때 포함시킨다.
- #ifdef _DEBUG: 디버그모드로 실행시킬 시 다음 코드를 포함시키겠다는 뜻.
- 게임 중에 플레이어가 죽거나, 게임 -> 메뉴로 넘어가는 등의 이벤트로 인해,
특정 입력의 기능이 변경되어야 하는 때가 있다.
- 이럴 때에는 반드시 입력 바인딩을 해제해주어야 한다.
-- 만약 입력 바인딩에 지워진 객체의 함수 포인터가 등록되어 있다면, 해당 입력을 할 시 존재하지 않는 객체에 대한 변수 값을 변경하려고 시도함으로써 에러를 생성할 수 있기 때문이다.
< 로직 >
- template 메소드로 선언한다.
- 인자로는 객체의 주소를 받는다.
- 현재 입력 바인딩을 순회하면서 받은 인자의 주소의 함수 포인터에 해당하는 값들을 모두 제거한다.
-- 입력 바인딩 순회
-> 입력 바인딩 안에 존재하는 VecFunc 이차원 배열의 행을 for문을 통해 순회
-> VecFunc 이차원 배열의 열을 iterator을 통해 순회
-> 등록된 Obj 값(객체 주소)와 인자로 받은 주소가 동일한지 확인
-> 동일할 시 동적 할당을 제거하고 해당 iteraor을 erase()
- CInput::AddBindFunction()와 CInput::~CInput()메소드와 비슷하므로 이 둘을 참고해서 작성하면 된다.
//해당 클래스 포인터에 해당하는 입력 바인딩을 전부 제거하는 메소드
//입력을 할당한 클래스의 소멸자에 해당 메소드를 자신의 주소를 인자로 전달하면 된다.
template <typename T>
void DeleteBindClass(T* ClassPtr)
{
std::unordered_map<std::string, BindKey*>::iterator iter = m_mapBindKey.begin();
std::unordered_map<std::string, BindKey*>::iterator iterEnd = m_mapBindKey.end();
while (iter != iterEnd)
{
//이차원 배열의 행을 순회한다.
for (size_t i = 0; i < (size_t)Input_Type::End; ++i)
{
//이차원 배열의 열을 iterator로 순회한다(erase 함수 사용하기 위함)
std::vector<BindFunction*>::iterator VecIter = iter->second->VecFunction[i].begin();
std::vector<BindFunction*>::iterator VecIterEnd = iter->second->VecFunction[i].end();
while (VecIter != VecIterEnd)
{
//들어온 인자와 함수포인터에 등록된 객체 주소와 같으면
if ((*VecIter)->Obj == ClassPtr)
{
//동적 할당을 우선 해제하고
SAFE_DELETE((*VecIter));
//해당 자리를 erase()를 통해 제거 + 앞으로 밀기 해준다.
VecIter = iter->second->VecFunction[i].erase(VecIter);
//새로 iterator의끝자리를 받는다.
VecIterEnd = iter->second->VecFunction[i].end();
continue;
}
++VecIter;
}
}
++iter;
}
}
- 작성이 완료되었으면 플레이어의 소멸자에서 해당 메소드를 실행시키고,
- 플레이어를 런타임 중에 삭제시켜 보고 문제가 발생하지 않는지 확인해본다.
//Player.cpp
CPlayer::~CPlayer()
{
//소멸자에서 제거 메소드 호출
CInput::GetInst()->DeleteBindClass<CPlayer>(this);
}
▼MainScene에 Ifdef를 통해 디버그용 플레이어 삭제 입력 구현
* 메소드 전체를 ifdef 하는 경우 선언 부분도 ifdef 해주어야 함!!
//MainScene.cpp
bool CMainScene::Init()
{
CScene::Init();
CreateObject<CPlayer>("Player");
//디버그용 플레이어 삭제 코드
#ifdef _DEBUG
CInput::GetInst()->AddBindKey("PlayerDeleteTest", 'P');
CInput::GetInst()->AddBindFunction<CMainScene>("PlayerDeleteTest", Input_Type::Down,
this, &CMainScene::DeletePlayerTestFunc);
#endif
CreateObject<CMonster>("Monster");
return true;
}
#ifdef _DEBUG
void CMainScene::DeletePlayerTestFunc()
{
CPlayer* Player = (CPlayer*)FindObject("Player");
Player->SetActive(false);
}
#endif
- 이후 디버그 모드로 실행시킨 뒤 'P'를 눌러 보면,
'WIN32API FrameWork > 한단계씩 직접 구현' 카테고리의 다른 글
28. 스킬 구현 1 - 토네이도 총알 (0) | 2022.05.23 |
---|---|
27. 스킬 쿨타임 (0) | 2022.05.23 |
25. GameObject의 주/종관계 형성 (0) | 2022.05.22 |
24. 입력을 받아 총을 발사하는 플레이어 (0) | 2022.05.21 |
23. 플레이어를 향해 총을 쏘는 몬스터 (0) | 2022.05.21 |