WinApi/TBI(더 바인딩 오브 아이작) 모작
[Win32API TBI 모작] 12. 아이템 (폭탄 & 픽업아이템)
Vfly
2025. 6. 2. 23:36
이번에는 몬스터를 죽였을때 나온는 픽업아이템(동전, 폭탄, 열쇠)와 황금방에서 나오는 아이템에 대해 알아보자.
전체 소스코드 : https://github.com/vfly1189/TBI
🏗️ 클래스 구조 및 상속 관계
CObject (부모 클래스)
└── CItem (추상 기본 클래스)
├── CPickUpItem (수집 가능한 아이템)
├── CCollectiblesItem (장식용/영구 아이템)
└── CBomb (폭탄 아이템)
📖 클래스별 상세 분석
1. CItem (기본 아이템 클래스)
역할: 모든 아이템의 기본 인터페이스 제공
주요 특징:
- CObject를 상속받아 게임 오브젝트의 기본 기능 활용
- Item 구조체를 통한 아이템 통계 관리
- 순수 가상 함수로 하위 클래스에서 반드시 구현해야 할 메서드 정의
- CLONE 매크로를 통한 객체 복제 패턴 구현
핵심 코드:
class CItem : public CObject {
private:
Item m_stItemStat; // 아이템 통계 데이터
public:
void SetItemStat(Item _ItemStat) { m_stItemStat = _ItemStat; }
Item GetItemStat() { return m_stItemStat; }
// 순수 가상 함수들로 인터페이스 강제
virtual void update() {}
virtual void render(ID2D1HwndRenderTarget* _pRendeR) {}
};
2. CPickUpItem (수집형 아이템)
역할: 플레이어가 수집할 수 있는 소모성 아이템 구현
주요 특징:
- enum 기반 타입 관리: PICKUP_ITEM_TYPE으로 아이템 종류 구분
- 초기화 시 타입별 설정: 생성자에서 타입에 따른 개별 설정
- 충돌 기반 상호작용: 플레이어와 충돌 시 효과 발동 및 자동 삭제
- 사운드 시스템 연동: 아이템 드롭/수집 시 효과음 재생
타입별 구현:
// HEART: 체력 회복
if (_eType == PICKUP_ITEM_TYPE::HEART) {
SetScale(Vec2(32.f, 32.f) * 2.f);
AddImage(Direct2DMgr::GetInstance()->GetStoredBitmap(L"pickup_drop_heart"));
GetCollider()->SetScale(Vec2(16.f, 13.f) * 2.f);
CSoundMgr::GetInstance()->Play(L"heart drop", 0.5f);
}
// COIN: 애니메이션 적용된 동전
else if (_eType == PICKUP_ITEM_TYPE::COIN) {
CreateAnimator();
GetAnimator()->CreateAnimation(/* 애니메이션 설정 */);
GetAnimator()->Play(L"pickup_drop_coin_animation", true, 1);
}
충돌 처리 로직:
void CPickUpItem::OnCollisionEnter(CCollider* _pOther) {
switch(m_ePickupType) {
case COIN:
CItemMgr::GetInstance()->GetPickUpItem().m_iCoin++;
break;
case HEART:
CPlayerMgr::GetInstance()->PlayerHeal(1);
break;
// ... 기타 타입들
}
DeleteObject(this); // 수집 후 즉시 삭제
}
3. CCollectiblesItem (수집품 아이템)
역할: 영구적으로 존재하는 장식용 또는 특수 효과 아이템
주요 특징:
- 복합 UI 구조: 받침대, 그림자, 아이템 이미지의 계층적 구성
- 동적 이미지 로딩: 아이템 번호와 태그 기반 이미지 경로 생성
- 자식 오브젝트 관리: vector<CObject*>로 여러 UI 요소 관리
UI 구성 시스템:
void CCollectiblesItem::start() {
// 1. 받침대 생성
CSpriteUI* pedestal = new CSpriteUI;
pedestal->AddImage(Direct2DMgr::GetInstance()->GetStoredBitmap(L"item_pedestal"));
// 2. 그림자 추가 (받침대의 자식으로)
CSpriteUI* item_shadow = pedestal->AddChild<CSpriteUI>(Vec2(0.f, -10.f));
// 3. 아이템 이미지 추가
selectedItem = pedestal->AddChild<CSpriteUI>(Vec2(0.f, -45.f));
// 동적 이미지 태그 생성
wstring item_image_tag = L"collectibles_";
if (m_stItemInfo.m_iNumber < 10)
item_image_tag += L"00" + std::to_wstring(m_stItemInfo.m_iNumber);
// ...
}
4. CBomb (폭탄 아이템)
역할: 시간 기반 상태 변화와 범위 공격을 가진 특수 아이템
주요 특징:
- 상태 머신 패턴: BOMB_STATE enum으로 점화/폭발 상태 관리
- 시간 기반 로직: 누적 시간을 통한 상태 전환 제어
- 동적 충돌 영역: 폭발 시 충돌 박스 크기 확장
- 애니메이션 제어: 상태별 애니메이션 재생/정지 관리
상태 머신 구현:
void CBomb::update() {
m_fAccTime += fDT; // 델타 타임 누적
if (m_fAccTime > m_fExplosionDuration) {
if (!m_bAnimationStopFlag) {
// 폭발 상태로 전환
m_eState = BOMB_STATE::EXPLODE;
m_bAnimationStopFlag = true;
// 애니메이션 변경
GetAnimator()->PauseAllAnimations();
GetAnimator()->Play(L"explosion", false, 1);
// 충돌 영역 확장 (32x32 → 96x96)
GetCollider()->SetScale(Vec2(96.f, 96.f) * 2.f);
}
// 폭발 후 일정 시간 뒤 삭제
if (m_fAccTime > m_fExplosionDuration + m_fAfterExplosionDuration) {
DeleteObject(this);
}
}
}