์ ๋ฒ ์๊ฐ์ ์์ฑํ๋ ํ๋ก๊ทธ๋จ์ ํ ๋๋ก ๊ฒ์์ ๋ง๋ ๋ค๊ณ ํ์ ๋ ๋ ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ ์ ์๋ค
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์ด
→ ์ฆ ํ๋ ์์ ์ญ์๋ ํ ํ๋ ์ ๋น ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ์๋ฏธํ๋ค.
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 ํ์ผ์ ์ถ๊ฐ ํด์ฃผ๋ฉด ๋๋ค.
'๐ค Study > winAPI' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[winAPI 06] Key Manager (1) | 2024.06.04 |
---|---|
[winAPI 05] Double Buffering (0) | 2024.06.04 |
[winAPI 03] Core class & Singleton (0) | 2024.04.08 |
[winAPI 02] ๋ง์ฐ์ค๋ก ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ & ๊ฒ์ ๋ฉ์ธ์ง ์ฒ๋ฆฌ ๊ตฌ์กฐ (0) | 2024.04.08 |
[winAPI 01] Handle, DC, Window Event & ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ (0) | 2024.04.03 |