본문 바로가기

개인공부/DirectX

Directx_20일차_애니메이션

 

 

수업내용

 

1.xml로 처리하면  애니메이션을쉽게 구현할수있다.

+  Quad객체 수정

더보기
Quad::Quad(wstring textureFile, bool isAdd, Vector2 startUV, Vector2 endUV, Vector2 pos)
{
	tag = "Quad";

	material->SetTexture(textureFile);
	size = material->GetTexture()->GetSize();

	mesh = new Mesh<VertexUV>();
	MakeMesh(startUV, endUV, pos);
	mesh->CreateMesh();
}

Quad::Quad(wstring textureFile, float x, float y, float width, float height)
{
	tag = "Quad";

	material->SetTexture(textureFile);
	size = material->GetTexture()->GetSize();

	Vector2 startUV = Vector2(x, y) / size;
	Vector2 cutSize = Vector2(width, height) / size;
	Vector2 endUV = startUV + cutSize;

	mesh = new Mesh<VertexUV>();
	MakeMesh(startUV, endUV);
	mesh->CreateMesh();
}

void Quad::MakeMesh(Vector2 startUV, Vector2 endUV, Vector2 pos)
{
	float left = pos.x - size.x * 0.5f;
	float right = pos.x + size.x * 0.5f;
	float top = pos.y + size.y * 0.5f;
	float bottom = pos.y - size.y * 0.5f;

	vector<VertexUV>& vertices = mesh->GetVertices();

	vertices.clear();
	vertices.emplace_back(left, top, startUV.x, startUV.y);
	vertices.emplace_back(right, top, endUV.x, startUV.y);
	vertices.emplace_back(left, bottom, startUV.x, endUV.y);
	vertices.emplace_back(right, bottom, endUV.x, endUV.y);

	vector<UINT>& indices = mesh->GetIndices();

	indices = { 0, 1, 2, 2, 1, 3 };
}

2.Frame 객체

 

헤더

더보기
class Frame
{
public:
	Frame(wstring textureFile, Vector2 startUV = Vector2(),
		Vector2 endUV = Vector2(1, 1), Vector2 pos = Vector2());
	Frame(wstring textureFile, float x, float y, float width, float height);
	~Frame();

	void Render();

	Vector2 GetSize() { return size; }

private:
	void MakeMesh(Vector2 startUV = Vector2(), Vector2 endUV = Vector2(1, 1), Vector2 pos = Vector2());

protected:
	Material* material;
	Mesh<VertexUV>* mesh;

	Vector2 size;
};

  cpp

더보기
#include "Framework.h"

Frame::Frame(wstring textureFile, Vector2 startUV, Vector2 endUV, Vector2 pos)
{
	material = new Material(textureFile);	
	size = (endUV - startUV) *  material->GetTexture()->GetSize();

	mesh = new Mesh<VertexUV>();
	MakeMesh(startUV, endUV, pos);
	mesh->CreateMesh();
}

Frame::Frame(wstring textureFile, float x, float y, float width, float height)
{
	material = new Material(textureFile);
	Vector2 textureSize = material->GetTexture()->GetSize();
	size = Vector2(width, height);

	Vector2 startUV = Vector2(x, y) / textureSize;
	Vector2 cutSize = size / textureSize;
	Vector2 endUV = startUV + cutSize;

	mesh = new Mesh<VertexUV>();
	MakeMesh(startUV, endUV);
	mesh->CreateMesh();
}

Frame::~Frame()
{
	delete material;
	delete mesh;
}

void Frame::Render()
{
	material->Set();
	mesh->Draw();
}

void Frame::MakeMesh(Vector2 startUV, Vector2 endUV, Vector2 pos)
{
	float left = pos.x - size.x * 0.5f;
	float right = pos.x + size.x * 0.5f;
	float top = pos.y + size.y * 0.5f;
	float bottom = pos.y - size.y * 0.5f;

	vector<VertexUV>& vertices = mesh->GetVertices();

	vertices.emplace_back(left, top, startUV.x, startUV.y);
	vertices.emplace_back(right, top, endUV.x, startUV.y);
	vertices.emplace_back(left, bottom, startUV.x, endUV.y);
	vertices.emplace_back(right, bottom, endUV.x, endUV.y);

	vector<UINT>& indices = mesh->GetIndices();

	indices = { 0, 1, 2, 2, 1, 3 };
}

3.Clip 객체  Frame&Clip은 출력에만 관여한다(world 가 없기때문에)

헤더

더보기
#pragma once

class Clip
{
private:
    const float FPS = 10.0f;

public:
    Clip(vector<Frame*> frames, bool isLoop = true, float speed = 1.0f);
    ~Clip();

    void Update();
    void Render();

    void Play();
    void Stop();

    void SetEndEvent(function<void()> event) { endEvent = event; }

    Frame* GetCurFrame() { return frames[curFrameNum]; }

private:
    vector<Frame*> frames;

    UINT curFrameNum = 0;

    float frameTime = 0.0f;
    float delayTime = 0.0f;
    float speed;    

    bool isLoop;
    bool isPlay = false;

    function<void()> endEvent = nullptr;

};

cpp

더보기
#include "Framework.h"

Clip::Clip(vector<Frame*> frames, bool isLoop, float speed)
    : frames(frames), isLoop(isLoop), speed(speed)
{
    delayTime = 1.0f / FPS;
}

Clip::~Clip()
{
    for (Frame* frame : frames)
        delete frame;
}

void Clip::Update()
{
    if (!isPlay) return;

    frameTime += speed * DELTA;

    if (frameTime < delayTime) return;

    frameTime -= delayTime;

    curFrameNum++;

    if (isLoop)
    {
        curFrameNum %= frames.size();
    }
    else
    {
        if (curFrameNum >= frames.size())
        {
            curFrameNum--;
            Stop();
        }
    }
}

void Clip::Render()
{
    frames[curFrameNum]->Render();
}

void Clip::Play()
{
    isPlay = true;
    frameTime = 0.0f;
    curFrameNum = 0;
}

void Clip::Stop()
{
    isPlay = false; 
    if (endEvent) endEvent();
    
}

4.tinyxml을 사용(깃허브)

 줍줍해오자~

 

5.애니메이션 출력

쿠키.h

더보기

#pragma once

class Cookie : public GameObject
{
private:
    enum State
    {
        IDLE, RUN, JUMP
    };

public:
    Cookie();
    ~Cookie();

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

private:
    void SetIdle();
    void LoadClip(string path, string file, bool isLoop, float speed = 1.0f);

private:
    vector<Clip*> clips;

    State curState = IDLE;
};

쿠키cppㅇ

더보기
#include "Framework.h"

Cookie::Cookie()
{

    LoadClip("Resources/Textures/Cookie/", "Kitty_Idle.xml", true);
    LoadClip("Resources/Textures/Cookie/", "Kitty_Run.xml", true);
    LoadClip("Resources/Textures/Cookie/", "Kitty_Jump.xml", false);
    clips[JUMP]->SetEndEvent(bind(&Cookie::SetIdle, this));
    
    clips[IDLE]->Play();
}

Cookie::~Cookie()
{
    for (auto clip : clips)
        delete clip;
}

void Cookie::Update()
{
    if (KEY->Down('1'))
    {
        curState = IDLE;
        clips[curState]->Play();
    }        

    if (KEY->Down('2'))
    {
        curState = RUN;
        clips[curState]->Play();
    }

    if (KEY->Down('3'))
    {
        curState = JUMP;
        clips[curState]->Play();
    }

    clips[curState]->Update();

    UpdateWorld();
}

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

    clips[curState]->Render();
}

void Cookie::SetIdle()
{
    curState = IDLE;
    clips[curState]->Play();
}

void Cookie::LoadClip(string path, string file, bool isLoop, float speed)
{
    tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument();
    document->LoadFile((path + file).c_str());

    tinyxml2::XMLElement* atlas = document->FirstChildElement();
    string textureFile = path + atlas->Attribute("imagePath");

    vector<Frame*> frames;
    tinyxml2::XMLElement* sprite = atlas->FirstChildElement();

    while (sprite != nullptr)
    {
        float x, y, w, h;
        x = sprite->FloatAttribute("x");
        y = sprite->FloatAttribute("y");
        w = sprite->FloatAttribute("w");
        h = sprite->FloatAttribute("h");

        frames.push_back(new Frame(ToWString(textureFile), x, y, w, h));

        sprite = sprite->NextSiblingElement();
    }

    clips.push_back(new Clip(frames, isLoop, speed));

    delete document;
}

6 .행동객체화

 

 프레임은 30프레임정도도 충분하다못해 넘쳐난다.

 

 

 

과제:

 

'개인공부 > DirectX' 카테고리의 다른 글

dx_22일차 Action_MapEditor  (0) 2024.03.28
DirectX 21일차_ Action / Animation  (0) 2024.03.27
DirectX 장비창 조합 구현  (0) 2024.03.25
DirectX 13일차 Camera  (0) 2024.03.14
DirectX 9일차  (0) 2024.03.08