League Of Legends - Link Select [winAPI 04] Timer
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค“ Study/winAPI

[winAPI 04] Timer

by GAMEMING 2024. 4. 9.
728x90

 

 

 

์ €๋ฒˆ ์‹œ๊ฐ„์— ์ž‘์„ฑํ–ˆ๋˜ ํ”„๋กœ๊ทธ๋žจ์„ ํ† ๋Œ€๋กœ ๊ฒŒ์ž„์„ ๋งŒ๋“ ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ  ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค

 

 

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 ํŒŒ์ผ์— ์ถ”๊ฐ€ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.