hyrule 2022. 5. 16. 16:00

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, 공용체

https://hyrule.tistory.com/86

 

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를 만들어 모아 놓자.

 

< 구현해야 할 것들 >

 

* 타이머 계산 방법

  1. 타이머의 초당 진동수를 받아놓음(ex.초당 1000.f번 진동)
  2. 이전 게임로직 한 사이클 시작 시간 기록(ex.100.f)
  3. 게임 한 사이클 종료 시간 기록(ex.200.f)
  4. (종료 시간 - 시작 시간) / 초당 진동수 = 한 프레임 그리는데 걸리는 시간(초 단위)
    1. 주의)타이머가 기록한 시간의 종류는 모두 LONG LONG 타입이고,
      우리가 구하는 DeltaTIme은 float 타입이다. 형변환 해줘야 함.
  5. (200 - 100) / 1000 = 0.1
  6. 한 프레임을 그리는데 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 함수로 우측 상단에 출력해 보자.

  * 실수 출력은 멀티바이트 문자 집합으로만 가능하다.

 

 

 

< 결과 > 

 

 

 

GameFrameworkStepbyStep_DeltaTIme.zip
0.79MB