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);
        }
    }
}