프로그래밍 공부
작성일
2023. 12. 8. 02:51
작성자
WDmil
728x90

캐릭터에 무기를 추가할것 이다.

 

캐릭터에 무기를 추가하는 방법은 두가지정도 사용할 수 있는데,

 

사용하는 무기를 그때그떄 넣어주어서 동적으로 부여하는 방법 과

 

모든 무기를 캐릭터에 집어넣어 두고 사용할 경우에만 해당 무기를 활성화시키는 방법

 

이 두가지를 사용할 수 있다.

 

우리는 모든 무기를 캐릭터에 넣어두고 사용하게 할것이다.

 

#pragma once

class Weapon
{
public:
    Weapon(SkillData data, Transform* player) : data(data), player(player)
    {}
    virtual ~Weapon() = default;

    virtual void Update() = 0;
    virtual void Render() = 0;
    virtual void GUIRender() {}

    void LevelUp();

protected:
    SkillData data;
    Transform* player;
};

 

우선 무기에 대한 헤더를 생성한다.

 

모든 무기는 위 헤더를 상속받아 사용하며, 무기의 데이터와 플레이어의 위치정보를 받아와 활용한다.

 

#pragma once

#pragma once

struct SkillData
{
    int key;
    string name;
    int level;
    string icon;
    float power;
    float speed;
    float interval;
    int count;
    float lifeTime;
    bool through;
    float knockback;
};

class SurvivalDataManager : public Singleton<SurvivalDataManager>
{
private:
    friend class Singleton;

    SurvivalDataManager();
    ~SurvivalDataManager();

public:
    void LoadTable();

    SkillData GetSkillData(int key) { return skillDatas[key]; }
    int GetSkillSize() { return skillDatas.size(); }

private:
    map<int, SkillData> skillDatas;
};

 

SkillData는 위와같다. 데이터는 csv로 불러와 사용하게 되며, 각각 의미있는 정보를 부여받아 저장한다.

 

무기의 키값, 이름, 무기의 래벨, 아이콘, 힘, 속도, 공격속도, 최대개수, 생존시간, 관통여부, 넉백여부 를 관여한다.

 

우선 구현해볼 무기는, 칼과 파이어볼이다.

 

파이어볼은 투사체로 플레이어->몬스터 위치로 발사되며, 항상 가장 가까운 몬스터의 위치로 발사된다.

 

칼은, 회전체로 플레이어를 중심으로 회전하며, 주변의 몬스터를 공격한다. 맞은 몬스터는 넉벡된다.

 

이러한 기초를 가지고 설계해보자.


#pragma once

class WeaponSword : public Weapon
{
private:
    const UINT MAX_COUNT = 6;
    const float RANGE = 5.0f;

public:
    WeaponSword(SkillData data, Transform* player);
    ~WeaponSword();

    void Update() override;
    void Render() override;
    void GUIRender() override;

private:
    vector<Sword*> swords;

    float angle = 0.0f;
};

 

무기정보를 상속받아 사용한다.

 

플레이어 주변을 회전하며 공격하는 성질을 가진다.

 

Weapon을 상속받아 사용함으로, 무기데이터를 활용한다.

 

#include "Framework.h"

WeaponSword::WeaponSword(SkillData data, Transform* player)
    : Weapon(data, player)
{
    swords.resize(MAX_COUNT);

    FOR(MAX_COUNT)
    {
        swords[i] = new Sword();        
        swords[i]->SetActive(i < data.count);
    }
}

WeaponSword::~WeaponSword()
{
    for (Sword*& sword : swords)
        delete sword;
}

void WeaponSword::Update()
{
    angle += data.speed * DELTA;    
    
    float step = XM_2PI / data.count;

    Vector3 pos = player->GetLocalPosition();

    FOR(data.count)
    {
        angle += step * i;

        pos.x += cos(angle) * RANGE;
        pos.z += sin(angle) * RANGE;

        swords[i]->SetLocalPosition(pos);
        swords[i]->SetLocalRotation({ XM_PIDIV2, -angle + XM_PIDIV2, 0.0f });
        swords[i]->Update();
    }
}

void WeaponSword::Render()
{
    for (Sword*& sword : swords)
        sword->Render();
}

void WeaponSword::GUIRender()
{
    for (Sword*& sword : swords)
        sword->GetCollider()->GUIRender();
}

 

무기의 업데이트정보 이다.

 

업데이트시, 무기의 최대개수에 따라 360도를 개수로 나누어 위치한다.

 

또한, 플레이어를 중심으로 회전하여 칼날부분이 항상 바깥쪽을 향하게 한다.

 


파이어볼

#pragma once

class WeaponFireball : public Weapon
{
public:
    WeaponFireball(SkillData data, Transform* player);
    ~WeaponFireball();

    void Update() override;
    void Render() override;

private:
    float time = 0.0f;
};

 

파이어볼은 무기와 비슷하게 생성되나, 생존시간만 관여한다.

 

FireBallManager에서 데이터를 확인하여, 생존시간이 초과하였을 경우 삭제하기 위함이다.

 

#include "Framework.h"

WeaponFireball::WeaponFireball(SkillData data, Transform* player)
    : Weapon(data, player)
{
    FireBallManager::Get();
}

WeaponFireball::~WeaponFireball()
{
    FireBallManager::Delete();
}

void WeaponFireball::Update()
{
    time += DELTA;

    if (time > data.interval)
    {
        time -= data.interval;

        Transform* monster = MonsterManager::Get()->GetClosestMonster(player->GetLocalPosition());

        if (monster)
        {
            Vector3 direction = (monster->GetLocalPosition() - player->GetLocalPosition()).GetNormalized();
            FireBallManager::Get()->Fire(player->GetLocalPosition(), direction, data);
        }
    }

    FireBallManager::Get()->Update();
}

void WeaponFireball::Render()
{
    FireBallManager::Get()->Render();
}

 

시간에 따라 속도값으로 타겟을 중심으로 목표방향으로 날아간다.

 

목표방향은 가장 가까운 몬스터를 MonsterManager에서 받아와서 사용하게 되낟.

 

direction으로 해당 방향을 정규화하고.

 

그 방향대로 이동한다.

 

만약 몬스터가 존재하지 않는다면 생성되지 않는다.

 

 

728x90