코딩 파트 / 개발자 관점에 관심이있는 사람들에 대한 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);
}
}
}