• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

DirectX11 공부 13일차(Animation)

14 Jun 2021

Reading time ~2 minutes

Animation

애니메이션이다. 3D 게임에서는 모델링의 움직임을 파일로 만들지만, 2D에서는 각각 이미지를 교체하는 식으로 애니메이션을 만들기 때문에 이미지를 교체하는 방식으로 만들었다.

Animation.h

#pragma once

enum class RepeatType : uint
{
	Once, Loop
};

struct Keyframe final
{
	Keyframe() = default;
	Keyframe(const D3DXVECTOR2& offset, const D3DXVECTOR2& size, const double& time)
		: offset(offset)
		, size(size)
		, time(time)
	{}

	D3DXVECTOR2 offset{ 0.0f, 0.0f };
	D3DXVECTOR2 size{ 0.0f,0.0f };
	double time{ 0.0 };
};

class Animation final
{
public:
	Animation(class Context* const context);
	~Animation();

	const RepeatType& GetRepeatType() { return repeat_type; }
	void SetRepeatType(const RepeatType& repeat_type) { this->repeat_type = repeat_type; }

	const D3DXVECTOR2 GetSpriteTextureSize() {		return sprite_texture_size;	}
	void SetSpriteTextureSize(const D3DXVECTOR2& size) { this->sprite_texture_size = size; }

	const std::shared_ptr<class D3D11_Texture>& GetSpriteTexture() const { return sprite_texture; }
	void SetSpriteTexture(const std::shared_ptr<class D3D11_Texture>& sprite_texture) { this->sprite_texture = sprite_texture; }
	void SetSpriteTexture(const std::string& path);

	const std::vector<Keyframe>& GetKeyframes() const { return keyframes; }
	void SetKeyframes(const std::vector<Keyframe>& keyframes) { this->keyframes = keyframes; }

	const Keyframe* GetKeyframeFromIndex(const uint& index);
	const uint GetKeyframeCount() const { return keyframes.size(); }
	
	void AddKeyframe(const Keyframe& keyframe);
	void AddKeyframe(const D3DXVECTOR2& offset, const D3DXVECTOR2& size, const double& time);

private:
	class Context* context = nullptr;
	RepeatType repeat_type = RepeatType::Loop;
	D3DXVECTOR2 sprite_texture_size = D3DXVECTOR2(1.0f, 1.0f);

	std::shared_ptr<class D3D11_Texture> sprite_texture;
	std::vector<Keyframe> keyframes;
};

하나하나 살펴보자

enum class RepeatType : uint
{
	Once, Loop
};

지금 이 애니메이션이 한번 실행할건디 계속해서 실행할건지 결정한다. 보통 공격은 한번하고 뛰거나 대기상태일땐 무한으로 도니까 나눠놨다.

struct Keyframe final
{
	Keyframe() = default;
	Keyframe(const D3DXVECTOR2& offset, const D3DXVECTOR2& size, const double& time)
		: offset(offset)
		, size(size)
		, time(time)
	{}

	D3DXVECTOR2 offset{ 0.0f, 0.0f };
	D3DXVECTOR2 size{ 0.0f,0.0f };
	double time{ 0.0 };
};

각 키프레임마다 어떤 스프라이트를 갖고올지 그리고 얼마나 실행시킬지에 관한 구조체이다.

void Animation::SetSpriteTexture(const std::string& path)
{
	sprite_texture = std::make_shared<D3D11_Texture>(context->GetSubsystem<Graphics>());
	sprite_texture->Create(path);
}

스프라이트 텍스쳐를 경로에 따라 갖고온다.


const Keyframe* Animation::GetKeyframeFromIndex(const uint& index)
{
	assert(index < keyframes.size());

	return &keyframes[index];
}

void Animation::AddKeyframe(const Keyframe& keyframe)
{
	keyframes.emplace_back(keyframe);
}

void Animation::AddKeyframe(const D3DXVECTOR2& offset, const D3DXVECTOR2& size, const double& time)
{
	keyframes.emplace_back(offset, size, time);
}

각 키프레임 추가하거나 갖고오는 함수이다.

하지만 Get부분을 보면 assert로 한번 막아주는 모습을 보인다.

이 부분은 if문을 줄이려고 사용했다 어차피 assert는 debug모드에서만 작동하니 완성품엔 없을 수 있으므로 막아뒀다.

Timer

매 프레임마다 얼마나 지났는지 확인하는 클래스이다.

Timer.h

class Timer final : public ISubsystem
{
public:
	Timer(class Context* const context);
	~Timer() = default;

	bool Initialize() override;
	void Update() override;

	const float GetDeltaTimeMS() const { return static_cast<float>(delta_time_ms); }
	const float GetDeltaTimeSEC() const { return static_cast<float>(delta_time_ms / 1000.0); }

private:
	double delta_time_ms = 0.0f;
	std::chrono::time_point<std::chrono::high_resolution_clock> previous_time;
};

매 프레임마다 시간을 밀리세컨드나 일반 세컨드로 갖고온다.

Timer.cpp

void Timer::Update()
{
	auto current_time = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double, std::milli> ms = current_time - previous_time;
	previous_time = std::chrono::high_resolution_clock::now();

	delta_time_ms = ms.count();
}

매 업데이트마다 시간을 측정!



DirectX Share Tweet +1