07. DeltaTime
https://hyrule.tistory.com/111
*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. (ex)
hyrule.tistory.com
[프레임과 게임 처리]
내 컴퓨터는 100프레임
PC방 컴퓨터는 200프레임
게임 코드는 1프레임당 한번 게임 로직을 처리
만약 게임 로직이 1프레임에 5씩 캐릭터를 이동시킨다면
내 컴퓨터에서 500 움직일 동안 PC방 컴퓨터는 1000을 움직이게 된다.
아주 심각한 문제
<해결법 - DeltaTime>
* 매 프레임마다 한 프레임을 그리는 데 걸렸던 시간을 변수에 저장한다.
* 그리고 다음 프레임을 그릴때 시간 단위를 위에서 저장한 변수로 처리한다.
* 그러면 프레임 수에 게임 속도가 빨라지거나 느려지는 문제가 발생하지 않는다.
* 그러므로 앞으로 모든 게임 로직 처리 함수에 인자로 DeltaTime을 넣어줘서 처리한다.
* 윈도우는 고해상도 타이머를 내장하고 있고, api에서 이 고해상도 타이머의 초당 진동수와 값을 얻어올 수 있다.
* 프레임과 프레임 사이의 시간을 구하고자 한다면 고해상도 타이머의 값을 얻어와서 구할 수 있다.
<사전 지식>
* LARGE_INTEGER, 공용체
LARGE_INTEGER , 공용체(Union)
* LARGE_INTEGER: 공용체(union) - 공용체는 메모리 공간을 공유하는 메모리 타입이다. * 32비트 기준 - DWORD LowPart = Unsigned int (4byte) ..
hyrule.tistory.com
QueryPerformanceFrequency(&LARGE_INTEGER)
- 들어온 LARGE_INTEGER 타입 변수의 '주소'에 현재 타이머의 1초당 진동수를 저장한다.
QueryPerformanceCounter(&LARGE_INTEGER)
- 들어온 LARGE_INTEGER 타입 변수의 '주소'에 현재 타이머의 시간을 기록한다.
char TimeText[64] = {};
sprintf_s(TimeText, "Deltatime: %.5f", DeltaTime);
2번 인자의 문자열 +
3번 인자의 데이터를 문자열로 바꾸어 합한 뒤
1번 인자에 삽입한다.
DeltaTime = 1.0f라고 가정하면
TimeText를 출력 시
"Deltatime: 1.00000"이 출력된다.
//신규 클래스
class CTimer
DeltaTime, 프레임 제한, 평균 프레임 연산 등의 작업을 수행할 클래스
GameManager의 하위 필터로 Timer를 만들어 모아 놓자.
< 구현해야 할 것들 >
* 타이머 계산 방법
- 타이머의 초당 진동수를 받아놓음(ex.초당 1000.f번 진동)
- 이전 게임로직 한 사이클 시작 시간 기록(ex.100.f)
- 게임 한 사이클 종료 시간 기록(ex.200.f)
- (종료 시간 - 시작 시간) / 초당 진동수 = 한 프레임 그리는데 걸리는 시간(초 단위)
- 주의)타이머가 기록한 시간의 종류는 모두 LONG LONG 타입이고,
우리가 구하는 DeltaTIme은 float 타입이다. 형변환 해줘야 함.
- 주의)타이머가 기록한 시간의 종류는 모두 LONG LONG 타입이고,
- (200 - 100) / 1000 = 0.1
- 한 프레임을 그리는데 0.1초가 지났으므로 다음 프레임을 그릴 때는 0.1초 지난 상태를 그려주면 된다.
CTimer::Init()
초기화 메소드. 값을 초기화 하고 초당 진동수를 등록해 준다.
CTimer::Update()
매 게임로직에서 실행될 메소드.
void 형식으로 CTimer 내부에서 선언한 변수에 따로 저장하거나,
float 형식으로 DeltaTime 값을 반환받아도 된다.
DeltaTime값은 GameManager에서 관리한다.
- DeltaTime을 계산
- 초당 프레임 수를 계산
- 초당 프레임 수 제한
CTimer::SetFrameLimit()
int값을 인자로 받아서, 초당 프레임을 인자만큼으로 제한한다.
0을 입력하면, 프레임 제한을 해제한다.
//코드 수정
class CGameManager
CTimer 구현이 끝났으면,
CGameManager 클래스에서 CTimer 클래스를 동적 할당 해준다.
게임로직이 실행되면, 가장 먼저 DeltaTime을 구해주고, 이후 실행되는 메소드들에 DeltaTime을 전달한다.
CGameManager::Render()
텍스트로 현재 DeltaTime과 FPS를 계산해서
TextOutA 함수로 우측 상단에 출력해 보자.
* 실수 출력은 멀티바이트 문자 집합으로만 가능하다.
< 결과 >