개인공부/DirectX

dx_23일차_Action

코딩기계 2024. 3. 29. 15:14

 

 

 

 

 

 

 

 

 

 

 

 

 

과제:

메인퀘스트 : 다음주 월요일까지

공격은 원거리 공격 근거리 공격 두개 구현

-> 몬스터 구현하고 공격 구현해서

피격 구현하기

 

1. 캐릭터 공격을 만든다

근접/원거리의 공통된부분을 묶는 cookieAttack을 만든다.

-> 근접공격 원거리공격을만들고 cookieAttack을 상속받게한다.

// 공격할때 점프, 이동 모두 할거기 떄문에 점프를 상속받아도 될거같았지만 

중복되더라도 깔끔하게 Attack에서 새로 만들어서 상속받자.

 

(충돌처리, ?)

cookieAttack.h/cpp

더보기
#pragma once

class CookieAttack : public CookieAction
{
protected:
	const float JUMP_POWER = 600.0f;
	const float FLOOR_EPSILON = 2.0f;

public:
	CookieAttack() = default;
	~CookieAttack() = default;

	virtual void Update() override;

protected:
	bool IsCollisionFloor();

};

////////////////////////////////////////
#include "Framework.h"


void CookieAttack::Update()
{

    velocity.y -= GRAVITY * DELTA;
    target->Translate(Vector2::Up() * velocity.y * DELTA);
    Move();

    Action::Update();
}

bool CookieAttack::IsCollisionFloor()
{
    RectCollider* cookie = ((Cookie*)target)->GetCollider();
    RectCollider* floor = FloorManager::Get()->Collision(cookie);

    if (floor == nullptr) return false;

    float cookieBottom = cookie->RightBottom().y;
    float floorTop = floor->RightTop().y;

    if (cookieBottom < floorTop && cookieBottom > floorTop - FLOOR_EPSILON)
    {
        target->Translate(Vector2::Up() * (floorTop - cookieBottom));
        return true;
    }

    return false;
}

 

이제 애니메이션이 끝나면 Idle 상태로 돌아오게 하기위해서 함수포인터 와 옵저버 패턴을 활용하기로 결정!

 근데 여기서 난관! 

SetEvent를 string 키값이 있는데 이를 만들어두기만하고 활용을 안했다.

클립에서의 SetEvent는 지정해주는 부분이 있어 이벤트를 만들어 넣을 수 있었는데

Action에서는 이가 없기에 새로 만들어주어야한다고 생각했다.

더보기

 

class Action
{
    virtual void Update();
    virtual void Start();
    virtual void End() {}

    void SetEvent(string key, Event event) { events[key] = event; }
    Clip* GetClip(int index) { return clips[index]; }
protected:
    vector<Clip*> clips;
    int curState = 0;

    map<string, Event> events;

};

이 때 End 순수가상함수에서 정의를 해버릴까? 아니면 업데이트에서 이벤트가 있을때 이를 실행해 줄까를 고민했다.

하지말자

 

그냥 클립의 이벤트를 가져다 넣어버리자

더보기
    actions[ATTACK_MELEE] = new CookieMelee(this);

    //옵저버패턴써서 넣고싶었는데 액션이 끝날때를 생각이 안난다. 좀만 미뤄두자

    actions[ATTACK_MELEE]->GetClip(0)->SetClipEvent(bind(&Cookie::SetIdle, this));

   
    actions[ATTACK_RANGE] = new CookieRange(this);
    actions[ATTACK_RANGE]->GetClip(0)->SetClipEvent(bind(&Cookie::SetIdle, this));

완료했더니 공격할때마다 중력을 받아서 아래로 내려가는 버그가 발생!

더보기

버그다 버그

이때! 아이들상태일때도 바닥과 충돌처리를 일으켜서 해결하는방법을 생각 ->  바로 실행해보자

이러면 많은곳에서 바닥충돌처리를 하니까 점프에서만 처리하지말고 cookieaction으로 옮기자

성공(!)

다음문제인 IDLE상태일떄도 중력추가해서 떨어지게끔하자

 

 

 

 

2. 적 만들기

(enemy또한 여러 상태가 있을거같으니까 후에 여러상태로 나누기 위해서 EnemyAction을 만들어준다.)

 

 EnemyAction.h/cpp

더보기
#pragma once
class EnemyAction : public Action
{
protected:
    const string PATH = "Resources/Textures/Cookie/Enemy/";
    const float GRAVITY = 980.0f;

public:
    EnemyAction() = default;
    EnemyAction(string file, bool isLoop, float speed = 1.0f);
    ~EnemyAction() = default;

    void SetTarget(Transform* target) { this->target = target; }

protected:
   // bool IsCollisionFloor();

protected:
    Transform* target;
    Vector2 velocity;


};

//
#include "Framework.h"

EnemyAction::EnemyAction(string file, bool isLoop, float speed)
	: Action("Resources/Textures/Cookie/Enemy/", file, isLoop, speed)
{
}

Enemy.h/cpp

더보기
#pragma once

class CookieEnemy : public GameObject
{
public:

    const float GRAVITY = 980.0f;
    const float FLOOR_EPSILON = 2.0f;

    enum State
    {
        IDLE, PATROL, ATTACK, DEAD
    };

public:
    CookieEnemy();
    ~CookieEnemy();

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

    RectCollider* GetCollider() { return collider; }

private:

    void SetAction(int state);

    bool IsCollisionFloor();

private:
    RectCollider* collider;

    map<State, Action*> actions;

    State curState = IDLE;

    Vector2 velocity;

};


///////////////////////////////
#include "Framework.h"

CookieEnemy::CookieEnemy()
{
    actions[IDLE] = new EnemyAction("Kitty_Idle.xml", true, 0.4f);
    actions[IDLE]->Start();


    collider = new RectCollider({ 100, 100 });
    collider->SetParent(this);
    collider->SetTag("EnemyBody");
    collider->Load();
}

CookieEnemy::~CookieEnemy()
{
    for (auto action : actions)
        delete action.second;

    delete collider;
}

void CookieEnemy::Update()
{

    velocity.y -= GRAVITY * DELTA;

    IsCollisionFloor();

    actions[curState]->Update();

    UpdateWorld();
    collider->UpdateWorld();
}

void CookieEnemy::Render()
{
    worldBuffer->Set(world);
    worldBuffer->SetVS(0);

    actions[curState]->Render();

    collider->Render();
}

void CookieEnemy::PostRender()
{
    RenderUI();
    collider->RenderUI();
}

void CookieEnemy::SetAction(int state)
{
    if (curState == state) return;

    curState = (State)state;
    actions[curState]->Start();
}

bool CookieEnemy::IsCollisionFloor()
{
    RectCollider* floor = FloorManager::Get()->Collision(collider);

    if (floor == nullptr) return false;

    float cookieBottom = collider->RightBottom().y;
    float floorTop = floor->RightTop().y;

    if (cookieBottom < floorTop && cookieBottom > floorTop - FLOOR_EPSILON)
    {
        Translate(Vector2::Up() * (floorTop - cookieBottom));
        return true;
    }

    return false;
}

 

플레이어와 충돌처리는 좀 있다 하고,  

총알 구현하러 ㄱㄱ

 

3. 총알구현

 

총알에 애니메이션을 넣느냐 마느냐에 따라 Quad 를 상속받을까 Action을 상속받을까 생각했는데

action을 상속받으면 콜라이더나 액티브 끄고 키는 기능을 다시 만들어야 해서

1).Quad를 상속 받는방법

이나 기본 불릿기능은 쿠키나,enemy처럼

2) GameObject 를 상속받고  세부적인 총알(관통, 차지, 일반)들이 Bullet을 상속받아서 bulletmanager로 관리하는방법 

3)  Action을 상속받기 : 신경쓸게 많아서 X