DirectX/DirectX 2D

DX2D_12 Time (System)

컴맹학자 2022. 12. 15. 00:23
728x90

게임에서 TIme은 정말 중요한 요소중 하나인데 우리가 알고 있는 FPS가 1초당 그림을 몇번 그려지는 냐에 따라 움직임이 버벅리거나 부드럽게 움직여지는데 중요한건 각 컴퓨터의 성능 마다 프레임 처리 속도 즉 시간 측정이 달라지기 때문에 공통으로 사용 하는 시간 클래스를 하나 만들어서 사용 할 예정

 

좀더 간략 하게 애기하면 A라는 컴퓨터는 1초당 3000 FPS 그려지는 속도를 가지는 성능 B라는 컴퓨터는 1초당 1000 FPS 가진다면 A와 B의 시간차이가 나기 때문에 같은 속도를 가진 캐릭터를 움직이여도 A라는 컴퓨터가 더 빠르게 움직이기 때문에 사용 하는 클래스

 

Time 클래스를 보면 QueryPerformanceCounter() 함수가 있는데 주파수 통해서 시간을 구해오는 기능 이라는것만 알아두면 된다. 


1. Time.h

1.중요한 부분은 ☆ 부분친 것이 주로 많이 사용하는 핵심이다.

2. Timer 클래스도 있는데 아직은 사용 안하는 클래스

더보기
#pragma once

class Time
{
public:
	static Time* Get();

	static void Create();
	static void Delete();

	static bool Stopped() { return isTimerStopped; }
	static float Delta() { return isTimerStopped ? 0.0f : timeElapsed; }  //공통(공용) 시간 ☆

	void Update();
	void Print();

	void Start();
	void Stop();

	float FPS() const { return framePerSecond; }
	float Running() const { return runningTime; }

private:
	Time(void);
	~Time(void);

	static Time* instance;					//< 싱글톤 객체

	static bool isTimerStopped;				//< 타이머 중지
	static float timeElapsed;				//< 이전 프레임으로부터 경과시간 (현재 시간과 이전 시간의 차이) ☆

	INT64 ticksPerSecond;					//< 초당 틱카운트
	INT64 currentTime;						//< 현재 시간 ☆
	INT64 lastTime;							//< 이전시간 ☆
	INT64 lastFPSUpdate;					//< 마지막 FPS 업데이트 시간
	INT64 fpsUpdateInterval;				//< fps 업데이트 간격

	UINT frameCount;						//< 프레임 수
	float runningTime;						//< 진행 시간
	float framePerSecond;					//< FPS
};

// Time 클래스에 같이 선언한 클래스
class Timer
{
public:
	Timer();
	~Timer();

	void Start(function<void()> func, int milliSec, UINT repeat = 0);
	void Stop();

private:
	mutex m;

	bool bComplete;
	UINT count;
};

2. Time.cpp

1. QueryPerformanceCounter() 기능을 통해서 시간값을 계산

2. Update()문 에서 진행시간 & FPS 시간값 구하고 있다.

더보기
#include "stdafx.h"
#include "Time.h"

Time* Time::instance = NULL;

bool Time::isTimerStopped = true;
float Time::timeElapsed = 0.0f;

Time::Time(void) :
	ticksPerSecond(0), currentTime(0), lastTime(0), lastFPSUpdate(0), fpsUpdateInterval(0),
	frameCount(0), runningTime(0), framePerSecond(0)
{
	//QueryPerformanceFrequency cpu의 주파수 통해서 시간을 계산
	QueryPerformanceFrequency((LARGE_INTEGER *)&ticksPerSecond);
	fpsUpdateInterval = ticksPerSecond >> 1;

	/*TwBar* bar = TweakBar::Get()->GetBar();
	TwAddVarRO(bar, "Time", TW_TYPE_FLOAT, &framePerSecond, "");*/
}

Time::~Time(void)
{

}

Time* Time::Get()
{
	assert(instance != NULL);

	return instance;
}

void Time::Create()
{
	assert(instance == NULL);

	instance = new Time();
}

void Time::Delete()
{
	SAFE_DELETE(instance);
}

//☆ 핵심 ☆
void Time::Update()
{
	if (isTimerStopped) return;

	//1. 현재시간을 가져와 시간 간격 및 진행 시간을 계산한다.
	QueryPerformanceCounter((LARGE_INTEGER *)&currentTime);
	timeElapsed = (float)(currentTime - lastTime) / (float)ticksPerSecond;
	runningTime += timeElapsed;

	//2. FPS Update
	frameCount++;
	if (currentTime - lastFPSUpdate >= fpsUpdateInterval)
	{
		float tempCurrentTime = (float)currentTime / (float)ticksPerSecond;
		float tempLastTime = (float)lastFPSUpdate / (float)ticksPerSecond;
		framePerSecond = (float)frameCount / (tempCurrentTime - tempLastTime);

		lastFPSUpdate = (INT64)currentTime;
		frameCount = 0;
	}

	lastTime = currentTime;
}

void Time::Print(){}

void Time::Start()
{
	if (!isTimerStopped)
		assert(false);

	QueryPerformanceCounter((LARGE_INTEGER *)&lastTime);
	isTimerStopped = false;
}

void Time::Stop()
{
	if (isTimerStopped)
		assert(false);

	INT64 stopTime = 0;
	QueryPerformanceCounter((LARGE_INTEGER *)&stopTime);
	runningTime += (float)(stopTime - lastTime) / (float)ticksPerSecond;
	isTimerStopped = true;
}

///////////////////////////////////////////////////////////////////////////////

Timer::Timer()
{
	bComplete = false;

	count = 0;
}

Timer::~Timer(){}

void Timer::Start(function<void()> func, int milliSec, UINT repeat)
{
	assert(bComplete == false);

	bComplete = false;
	thread t([=]()
	{
		while (true)
		{
			if (repeat > 0 && count == repeat)
				break;

			if (bComplete == true)
				break;

			count++;
			Sleep(milliSec);

			if (bComplete == true)
				break;

			func();
		}

		Stop();
	});
	t.detach();
}

void Timer::Stop()
{
	count = 0;

	bComplete = true;
}

3. 수정

stdafx.h

Time 클래스를 사용 할 수있게 미리 컴파일러 헤더에 필요한 부분을 선언

#include <mutex>		// thread 임계구역 구별용 (Time)
#include "System/Time.h"
#define SAFE_DELETE(p) { if(p) { delete (p); (p) = nullptr; } }

 

Device.cpp -> Running()

ImGui 생성및 사용 방법으로 값을 셋팅

WPARAM Running()
{
	MSG msg;
	ZeroMemory(&msg, sizeof(MSG));
	
	// 싱글톤
	ImGui::Create(Hwnd, Device, DeviceContext);
	ImGui::StyleColorsDark(); //테마 (안해도됨)
	
	//System
	Key = new Keyboard();
	Time::Create();
	Time::Get()->Start();

	InitScene();
	while (true)
	{
		if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) //종료
		{
			if (msg.message == WM_QUIT)
				break;

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			Time::Get()->Update();
			ImGui::Update();
			Update();
			Render();
		}
	}
	DestroyScene();

	Time::Delete();
	SafeDelete(Key);
	ImGui::Delete();
    return msg.wParam;
}

4. 확인

 

Scene.cpp -> Update()

Update() 함수 안에 해당 코드 작성후 실행 하면 ImGui로 확인 해보면 0.1초씩 증가 및 FPS 값도 측정

	//FPS
	ImGui::Text("%.1f", ImGui::GetIO().Framerate);
	ImGui::Text("FPS : %.1f", Time::Get()->FPS());
	ImGui::Text("Running Time : %.1f", Time::Get()->Running());

 

 

https://github.com/ascher8159/DX2D

DX2D_12 Time

'DirectX > DirectX 2D' 카테고리의 다른 글

DX2D_14 Texture (Sampler state, Blend State)  (0) 2023.03.22
DX2D_13 Rect_Control  (1) 2022.12.24
DX2D_11 Rect_Control (상속, 다형성)  (0) 2022.12.14
DX2D_10 Rect  (0) 2022.12.07
DX2D_9 WVP2  (1) 2022.12.04