λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

[winAPI 04] Timer

@GAMEMING2024. 4. 9. 23:59

 

 

 

μ €λ²ˆ μ‹œκ°„μ— μž‘μ„±ν–ˆλ˜ ν”„λ‘œκ·Έλž¨μ„ ν† λŒ€λ‘œ κ²Œμž„μ„ λ§Œλ“ λ‹€κ³  ν–ˆμ„ λ•Œ  두 κ°€μ§€ λ¬Έμ œκ°€ μžˆμ„ 수 μžˆλ‹€

 

 

1. 컴퓨터가 느린 μ‚¬λžŒκ³Ό λΉ λ₯Έ μ‚¬λžŒμ˜ 이동 속도가 λ‹¬λΌμ§ˆ 수 μžˆλ‹€. 즉 CPU의 속도에 따라 처리 속도가 달라져 1초 λ‹Ή 이동 거리 속도가 λ‹€λ₯Έ λ¬Έμ œκ°€ λ°œμƒν•œλ‹€.

 

2. μ •μˆ˜ λ‹¨μœ„λ‘œ μ΄λ™ν•˜κ³  μžˆμ–΄μ„œ 1μ΄ˆμ— μ—„μ²­λ‚˜κ²Œ λ§Žμ€ 거리λ₯Ό μ΄λ™ν•˜κ³  μžˆλ‹€.

 

μš°μ„  μ‹€μˆ˜ λ‹¨μœ„λ‘œ 이동 μ‹œμΌœ 보도둝 ν•˜μž

κΈ°μ‘΄ Object classμ—μ„œ POINT 객체둜 λ˜μ–΄ 있던 것을 vec2 λΌλŠ” 객체둜 λ§Œλ“€κ² λ‹€. μ—¬κΈ°μ„œ vec2λŠ” μš°λ¦¬κ°€ μ•„λŠ” μˆ˜ν•™μ  2차원 κ°œλ…μ΄λ‹€.

 

// new header file : struct.h

#pragma once
struct Vec2 {
	float x;
	float y;

	Vec2()
		:x(0.f)
		,y(0.f)
	{}

	Vec2(float _x, float _y)
		:x(_x)
		,y(_y)
	{}

	Vec2(int _x, int _y)
		:x((float)_x)
		,y((float)_y)
	{}
};



// pch.h -> struct.hλ₯Ό 미리 컴파일된 ν—€λ”λ‘œ μΆ”κ°€.

#pragma once
#include <windows.h>
#include <iostream>

#include "define.h"
#include "struct.h"



// Object.h μˆ˜μ •

class Object {
private:
	Vec2	vPos;
	Vec2	vScale;

public:
	Object();
	~Object();

	void setPos(Vec2 _vPos) { vPos = _vPos; }
	void setScale(Vec2 _vScale) { vScale = _vScale; }

	Vec2 getPos() { return vPos; }
	Vec2 getScale() { return vScale; }

};



// Object.cpp μˆ˜μ •

#include "pch.h"
#include "Object.h"

Object::Object()
	: vPos{}
	, vScale{}
{
}

Object::~Object()
{
}



// Core.cpp μˆ˜μ •

// Init() ν•¨μˆ˜
	obj.setPos(Vec2((float)(ptResolution.x / 2), (float)(ptResolution.y / 2)));
	obj.setScale( Vec2(100, 100 ));
    
    
// Update() ν•¨μˆ˜
void Core::Update()   
{
	Vec2 vPos = obj.getPos();

	if (GetAsyncKeyState(VK_LEFT) & 0x8000) {   
		vPos.x -= 0.01f  
	}
	if (GetAsyncKeyState(VK_RIGHT) & 0x8000) {   
		vPos.x += 0.01f
	}

	obj.setPos(vPos);
}



// Render() ν•¨μˆ˜
void Core::Render() 
{
	Vec2 vPos = obj.getPos();
	Vec2 vScale = obj.getScale();

	Rectangle(hDC,    //rectangle은 μ •μˆ˜λ₯Ό μš”κ΅¬ν•¨
		int(vPos.x - vScale.x / 2.f),
		int(vPos.y - vScale.y / 2.f),
		int(vPos.x + vScale.x / 2.f),
		int(vPos.y + vScale.y / 2.f));

}

 

 

 

μš°μ„  κΈ°μ‘΄ Object의 μ’Œν‘œμ™€ 크기 λ³€μˆ˜κ°€ publicμ—μ„œ private둜 μ„ μ–Έ 됨에 따라 이에 μ ‘κ·Όν•  수 μžˆλŠ” Setν•¨μˆ˜μ™€ Getν•¨μˆ˜κ°€ ν•„μš”ν•˜λ‹€. Set()은 λ§€κ°œλ³€μˆ˜ 값을 톡해 값을 μ„€μ •ν•  수 μžˆλŠ” ν•¨μˆ˜κ³ , Get()은 각 λ³€μˆ˜μ˜ 값을 μ–»μ–΄μ˜¬ 수 μžˆλŠ” ν•¨μˆ˜λ‹€. 이런 ν•¨μˆ˜λ“€μ„ 보톡 μΈν„°νŽ˜μ΄μŠ€ ν•¨μˆ˜λΌκ³  ν•œλ‹€.

 

μœ„μ˜ μ½”λ“œλ₯Ό μ μš©ν•˜λ©΄ μ•„λž˜μ™€ 같이 μ €λ²ˆ μ‹œκ°„κ³ΌλŠ” λ‹€λ₯΄κ²Œ 눈으둜 확인할 수 μžˆμ„ μ •λ„μ˜ μ›€μ§μž„μ„ λ³Ό 수 μžˆλ‹€. 이전 것을 λ¬΄νš¨ν™”ν•˜λŠ” μž‘μ—…μ„ 아직 ν•˜μ§€ μ•Šμ•„μ„œ μ•„λž˜μ™€ 같이 λ‚˜μ˜¨λ‹€. λ¬΄νš¨ν™” μž‘μ—…μ€ λ’€μ—μ„œ ν•˜κ² λ‹€.

 

 

 

 

 

자 근데 μ •μˆ˜μ—μ„œ μ‹€μˆ˜λ‘œ λ°”κΎΈμ—ˆλ‹€κ³  ν•΄μ„œ μ•„κΉŒ μ–ΈκΈ‰ν–ˆλ˜ 1번 λ¬Έμ œλŠ” μ—†μ–΄μ§€μ§€ μ•ŠλŠ”λ‹€. μ΄λŠ” κ²Œμž„κ³Ό 같은 ν”„λ‘œκ·Έλž¨μ—μ„œ κ²Œμž„μ˜ λ°ΈλŸ°μŠ€μ™€ 곡정성을 κΉ° 수 μžˆλŠ” λΆ€λΆ„μž„μœΌλ‘œ ν˜„μ‹€ μ‹œκ°„μ„ λ°˜μ˜ν•˜μ—¬ 1μ΄ˆμ— μ–΄λŠ 정도 이동할 κ²ƒμΈμ§€λŠ” λ°˜μ˜ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€. 

 

μ•žμœΌλ‘œ μ‹œκ°„μ„ κ΄€λ¦¬ν•˜λŠ” TimeManager Classλ₯Ό λ§Œλ“€μ–΄λ³΄μž.

 

// TimeManager.h

#pragma once
class TimeManager{
	SINGLE(TimeManager);
private:
	LARGE_INTEGER curCount;
	LARGE_INTEGER prevCount;
	LARGE_INTEGER prequency;

	double        dDT; 
	double        dAcc; 
	UINT          iCallCount; 
	UINT          iFPS;       

public:
	void Init();
	void update();
	double getDT() { return dDT; }
	float  getfDT() { return (float)dDT; }
};


// TimeManager.cpp

#include "pch.h"
#include "TimeManager.h"

#include "Core.h"

TimeManager::TimeManager()
	:curCount{}
	,prevCount{}
	,prequency{}
	,dDT(0.)
	,dAcc(0.)
	,iCallCount(0)
{

}

TimeManager::~TimeManager()
{

}

void TimeManager::Init()
{
	QueryPerformanceCounter(&prevCount);
	QueryPerformanceFrequency(&prequency); 
}

void TimeManager::update()
{
	QueryPerformanceCounter(&curCount);
	dDT = (double) (curCount.QuadPart - prevCount.QuadPart) / (double)prequency.QuadPart;

	prevCount = curCount;

	++iCallCount;
	dAcc += dDT; 

	if (dAcc >= 1.) {
		iFPS = iCallCount;
		dAcc = 0.;
		iCallCount = 0;

		wchar_t szBuffer[255] = {};
		swprintf_s(szBuffer,L"FPS : %d, DT : %f", iFPS, dDT);
		SetWindowText(Core::Instance()->getMainHandle(), szBuffer);
	}	
}

 

 

 

보톡 κ²Œμž„μ—μ„œμ˜ μ‹œκ°„μ€ FPS둜 많이 ν‘œν˜„λœλ‹€. 

 

1μ΄ˆμ— 2ν”„λ ˆμž„μ΄λΌκ³  ν•˜λ©΄, 1ν”„λ ˆμž„ λ‹Ή 0.5초

1μ΄ˆμ— 10ν”„λ ˆμž„μ΄λΌ ν•˜λ©΄, 1ν”„λ ˆμž„ λ‹Ή 0.1초

 

→ 즉 ν”„λ ˆμž„μ˜ μ—­μˆ˜λŠ” ν•œ ν”„λ ˆμž„ λ‹Ή κ±Έλ¦¬λŠ” μ‹œκ°„μ„ μ˜λ―Έν•œλ‹€.

 

 

TimeManager.h

 

LARGE_INTEGER : μ‹œκ°„μ„ μΈ‘μ •ν•˜κΈ° μœ„ν•œ κ°’

curCount :  ν˜„μž¬ μ‹œκ°„ / prevCount : 이전 μ‹œκ°„ / prequency : μ„±λŠ₯ μΉ΄μš΄ν„°κ°€ μ΄ˆλ‹Ή λͺ‡ 번 μ§„ν–‰λ˜λŠ”μ§€ μ €μž₯

 

dDT : 두 ν”„λ ˆμž„ μ‚¬μ΄μ˜ μ‹œκ°„ κ°’μœΌλ‘œ ν˜„μž¬ μ‹œκ°„κ³Ό 이전 μ‹œκ°„μ˜ 차이λ₯Ό κ΅¬ν•œ ν›„ μ‹œμŠ€ν…œ μ„±λŠ₯ μΉ΄μš΄ν„°μ˜ 주파수둜 λ‚˜λˆ  계산됨

dAcc : λˆ„μ  κ²½κ³Ό μ‹œκ°„μœΌλ‘œ 1초λ₯Ό μ΄ˆκ³Όν•˜λ©΄ FPS κ³„μ‚°ν•˜κ³  μ΄ˆκΈ°ν™”

iCallCount : Update ν•¨μˆ˜ 호좜 횟수 μ €μž₯

iFPS : ν”„λ ˆμž„ μ†λ„λ‘œ 1μ΄ˆλ‹Ή Update호좜 횟수

 

 

 

Init() ν•¨μˆ˜

QueryPerformanceCounter() : prevCount λ³€μˆ˜μ— ν˜„μž¬ 카운트λ₯Ό μ €μž₯함.

QueryPerformanceFrequency() : prequency λ³€μˆ˜μ— 1μ΄ˆλ‹Ή 카운트 횟수λ₯Ό μ €μž₯함.

 

QueryPerformanceCounter() 
: ν˜„μž¬ μ‹œκ°„μ„ μΈ‘μ •ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λ©° μ‹œμŠ€ν…œμ˜ μ„±λŠ₯ μΉ΄μš΄ν„° 값을 κ°€μ Έμ™€μ„œ ν˜„μž¬ μ‹œκ°„μ„ λ‚˜νƒ€λƒ„

QueryPerformanceFrequency() 
: μ„±λŠ₯ μΉ΄μš΄ν„°μ˜ 주파수(μ΄ˆλ‹Ή 클럭 ν‹±μ˜ 수)λ₯Ό μΈ‘μ •ν•˜λŠ” 데 μ‚¬μš©, 이 값을 μ΄μš©ν•΄ μ„±λŠ₯ μΉ΄μš΄ν„° κ°’μ˜ λ‹¨μœ„λ₯Ό μ‹œκ°„ λ‹¨μœ„λ‘œ λ³€ν™˜ κ°€λŠ₯함.

 

 

 

 

 

Update() ν•¨μˆ˜

curCount λ³€μˆ˜μ— ν˜„μž¬ 카운트λ₯Ό μ €μž₯함. dDT λ³€μˆ˜μ— 이전 ν”„λ ˆμž„μ˜ μΉ΄μš΄νŒ…κ³Ό ν˜„μž¬ ν”„λ ˆμž„ μΉ΄μš΄νŒ… κ°’μ˜ 차이에 주파수 값을 λ‚˜λˆ  두 ν”„λ ˆμž„ κ°„μ˜ μ‹œκ°„ 값을 μ €μž₯함 prevCount λ³€μˆ˜μ— 이전 카운트 값을 ν˜„μž¬ κ°’μœΌλ‘œ κ°±μ‹ ν•˜μ—¬ μ €μž₯함 (λ‹€μŒ 계산을 μœ„) Updateν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜μ—ˆμŒμœΌλ‘œ iCallCount 횟수λ₯Ό ν•˜λ‚˜ λ†’μ—¬ μ €μž₯함 dAcc λ³€μˆ˜μ— dDT을 λˆ„μ  ν•΄μ„œ μ €μž₯ν•˜μ—¬ 흐λ₯Έ μ‹œκ°„μ„ λ‚˜νƒ€λƒ„.

→ dAcc λ³€μˆ˜μ˜ 값이 1 이상이면 μ•„λž˜ μž‘μ—…λ“€μ„ μˆ˜ν–‰ν•¨.

 

 

 

 

- μ‹œκ°„ μ μš©ν•΄μ„œ μ‚¬κ°ν˜• μ΄λ™ν•˜κΈ°

// Core.cpp μΆ”κ°€

#include "TimeManager.h"

// Init() ν•¨μˆ˜ μΆ”κ°€

	// Managerμ΄ˆκΈ°ν™”
	TimeManager::Instance()->Init();
    
    
// Progress() ν•¨μˆ˜ μΆ”κ°€

	// Manager update
	TimeManager::Instance()->update();
    
    
// Update() ν•¨μˆ˜ μˆ˜μ •

void Core::Update()   
{
	Vec2 vPos = obj.getPos();

	if (GetAsyncKeyState(VK_LEFT) & 0x8000) {   
		vPos.x -= 200.f * TimeManager::Instance()->getfDT();   
	}
	if (GetAsyncKeyState(VK_RIGHT) & 0x8000) {   
		vPos.x += 200.f * TimeManager::Instance()->getfDT();
	}

	obj.setPos(vPos);
}

 

 

 

상단바에 FPS와 DT 값을 좜λ ₯λœλ‹€. DT(두 ν”„λ ˆμž„ μ‚¬μ΄μ˜) 값을 μ΄μš©ν•΄μ„œ 1μ΄ˆμ— 이동해야 ν•˜λŠ” 거리λ₯Ό κ³„μ‚°ν•œλ‹€. 이것은 CPU μ„±λŠ₯κ³ΌλŠ” 상관없이 ν˜„μ‹€ μ‹œκ°„μ— 맞좰 μ§„ν–‰λ˜λ„λ‘ ν•œλ‹€.

 

 

 

μ•žμœΌλ‘œ μ‹œκ°„μ„ μ΄μš©ν•΄μ„œ κ²Œμž„μ„ κ΅¬ν˜„ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— 자주 μ‚¬μš©ν•  κ²ƒμž„μœΌλ‘œ μ•„λž˜μ²˜λŸΌ 맀크둜둜 μ§€μ •ν•΄λ‘μž. μ €λ²ˆ μ‹œκ°„μ— λ§Œλ“€μ–΄ λ†“μ•˜λ˜ define.h νŒŒμΌμ— μΆ”κ°€ ν•΄μ£Όλ©΄ λœλ‹€.

 

 

 

 

 

 

728x90
GAMEMING
@GAMEMING :: GAMEMING

< School > ν•œκ΅­κ³΅ν•™λŒ€ν•™κ΅ κ²Œμž„κ³΅ν•™κ³Ό λ²€μ²˜μ°½μ—… 뢀전곡 < Instagram > μž‘μ—… @game.plan.diary 본계 @mi.___.02

μ†Œν†΅ ν™˜μ˜ν•©λ‹ˆλ‹€ πŸ‘€

λͺ©μ°¨