코딩 파트 / 개발자 관점에 관심이있는 사람들에 대한 Journeyman Geek의 답변 (내 편집이 거부 되었기 때문에)에 대한 추가로 :
프로그래머의 관점에서, 관심이있는 사람들을 위해 DOS 시간은 모든 CPU 틱이 중요한 시간이되었으므로 프로그래머는 코드를 최대한 빨리 유지했습니다.
프로그램이 최대 CPU 속도로 실행되는 일반적인 시나리오는 다음과 같습니다 (의사 C).
int main()
{
while(true)
{
}
}
이것은 영원히 실행될 것입니다.이 코드 스 니펫을 의사 DOS 게임으로 바꾸어 봅시다.
int main()
{
bool GameRunning = true;
while(GameRunning)
{
ProcessUserMouseAndKeyboardInput();
ProcessGamePhysics();
DrawGameOnScreen();
//close game
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
DrawGameOnScreen함수가 더블 버퍼링 / V- 싱크를 사용 하지 않는 한 (DOS 게임이 만들어진 날에는 비용이 많이 들었습니다), 게임은 최대 CPU 속도로 실행됩니다. 현대의 모바일 i7에서는 랩톱 구성 및 현재 CPU 사용량에 따라 초당 약 1,000,000 ~ 5,000,000 회 실행됩니다.
즉, 64 비트 창에서 최신 CPU로 작동하는 DOS 게임을 얻을 수 있다면 물리 처리가 "가정"한다고 가정하면 사람이 재생하기에는 너무 빠른 1000 (1000!) 이상의 FPS를 얻을 수 있습니다. 50-60fps.
현재 개발자가 할 수있는 일은 다음과 같습니다.
- 게임에서 V-Sync 사용 (* 윈도우 응용 프로그램에는 사용할 수 없음 ** (일명 전체 화면 응용 프로그램에서만 사용 가능))
- FPS 속도에 관계없이 게임 / 프로그램을 동일한 속도로 효과적으로 실행하는 시간 차이에 따라 마지막 업데이트 간의 시간 차이를 측정하고 물리를 업데이트하십시오.
- 프로그래밍 방식으로 프레임 속도 제한
*** 그래픽 카드 / 드라이버 / OS 구성에 따라 가능할 수 있습니다.
포인트 1의 경우 실제로 "프로그래밍"이 아니기 때문에 표시 할 예가 없습니다. 그래픽 기능 만 사용하고 있습니다.
포인트 2와 3에 대해서는 해당 코드 스 니펫과 설명을 보여줍니다.
2 :
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
while(GameRunning)
{
TimeDifference = GetCurrentTime()-LastTick;
LastTick = GetCurrentTime();
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
DrawGameOnScreen();
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
여기에서 사용자 입력과 물리가 시간 차이를 고려한 것을 볼 수 있지만 루프가 가능한 빨리 실행되기 때문에 여전히 화면에 1000+ FPS를 얻을 수 있습니다. 물리 엔진은 시간이 얼마나 걸 렸는지 알기 때문에 "가정 없음"또는 "특정 프레임 속도"에 의존 할 필요가 없으므로 모든 CPU에서 게임이 동일한 속도로 작동합니다.
삼:
예를 들어 30 FPS로 프레임 속도를 제한하기 위해 개발자가 할 수있는 작업은 실제로 어렵지 않습니다.
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
double FPS_WE_WANT = 30;
//how many milliseconds need to pass before we need to draw again so we get the framerate we want?
double TimeToPassBeforeNextDraw = 1000.0/FPS_WE_WANT;
//For the geek programmers: note, this is pseudo code so I don't care for variable types and return types..
double LastDraw = GetCurrentTime();
while(GameRunning)
{
TimeDifference = GetCurrentTime()-LastTick;
LastTick = GetCurrentTime();
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
//if certain amount of milliseconds pass...
if(LastTick-LastDraw >= TimeToPassBeforeNextDraw)
{
//draw our game
DrawGameOnScreen();
//and save when we last drawn the game
LastDraw = LastTick;
}
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
여기서 발생하는 것은 프로그램이 몇 밀리 초가 경과했는지 계산하고 특정 양에 도달하면 (33ms) 게임 화면을 다시 그리며 ~ 30 근처의 프레임 속도를 효과적으로 적용합니다.
또한 개발자에 따라 위 코드를 약간 수정하여 모든 처리를 30fps로 제한하도록 선택할 수 있습니다.
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
double FPS_WE_WANT = 30;
//how many miliseconds need to pass before we need to draw again so we get the framerate we want?
double TimeToPassBeforeNextDraw = 1000.0/FPS_WE_WANT;
//For the geek programmers: note, this is pseudo code so I don't care for variable types and return types..
double LastDraw = GetCurrentTime();
while(GameRunning)
{
LastTick = GetCurrentTime();
TimeDifference = LastTick-LastDraw;
//if certain amount of miliseconds pass...
if(TimeDifference >= TimeToPassBeforeNextDraw)
{
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
//draw our game
DrawGameOnScreen();
//and save when we last drawn the game
LastDraw = LastTick;
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
}
몇 가지 다른 방법이 있으며 그중 일부는 정말 싫어합니다.
예를 들어을 사용 sleep(<amount of milliseconds>)합니다.
이것이 프레임 속도를 제한하는 한 가지 방법이라는 것을 알고 있지만 게임 처리에 3 밀리 초 이상이 걸리면 어떻게됩니까? 그리고 당신은 잠을 실행합니다 ...
이로 인해 발생하는 프레임 속도보다 프레임 속도가 느려집니다 sleep().
예를 들어 16ms의 절전 시간을 보자. 이렇게하면 프로그램이 60Hz에서 실행됩니다. 이제 데이터, 입력, 그리기 및 모든 자료를 처리하는 데 5 밀리 초가 걸립니다. 우리는 하나의 루프에 대해 21 밀리 초에 있습니다. 이는 50 hz보다 약간 작습니다. 그러나 여전히 60 hz에있을 수 있지만 수면 때문에 불가능합니다.
한 가지 해결책은 처리 시간을 측정하고 원하는 수면에서 처리 시간을 차감하여 "버그"를 수정하는 형태로 적응 형 절전 모드 를 만드는 것입니다 .
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
long long NeededSleep;
while(GameRunning)
{
TimeDifference = GetCurrentTime()-LastTick;
LastTick = GetCurrentTime();
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
//draw our game
DrawGameOnScreen();
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
NeededSleep = 33 - (GetCurrentTime()-LastTick);
if(NeededSleep > 0)
{
Sleep(NeededSleep);
}
}
}