μ λ² μκ°μ μμ±νλ νλ‘κ·Έλ¨μ ν λλ‘ κ²μμ λ§λ λ€κ³ νμ λ λ κ°μ§ λ¬Έμ κ° μμ μ μλ€
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 |