Là một bổ sung cho câu trả lời của Journeyman Geek (vì bản chỉnh sửa của tôi đã bị từ chối) cho những người quan tâm đến quan điểm của nhà phát triển / phần mã hóa:
Từ góc độ lập trình viên, đối với những người quan tâm, thời gian DOS là thời điểm mà mọi dấu kiểm CPU đều quan trọng để các lập trình viên giữ mã nhanh nhất có thể.
Một kịch bản điển hình trong đó bất kỳ chương trình nào sẽ chạy ở tốc độ CPU tối đa là đơn giản này (giả C):
int main()
{
while(true)
{
}
}
Điều này sẽ chạy mãi mãi, bây giờ, hãy biến đoạn mã này thành trò chơi giả DOS:
int main()
{
bool GameRunning = true;
while(GameRunning)
{
ProcessUserMouseAndKeyboardInput();
ProcessGamePhysics();
DrawGameOnScreen();
//close game
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
trừ khi các DrawGameOnScreen
chức năng sử dụng bộ đệm đôi / đồng bộ hóa V (vốn khá đắt tiền vào thời mà trò chơi DOS được tạo ra), trò chơi sẽ chạy ở tốc độ CPU tối đa. Trên một thiết bị di động i7 hiện đại, nó sẽ chạy ở mức khoảng 1.000.000 đến 5.000.000 lần mỗi giây (tùy thuộc vào cấu hình máy tính xách tay và việc sử dụng cpu hiện tại).
Điều này có nghĩa là nếu tôi có thể khiến bất kỳ trò chơi DOS nào hoạt động trên CPU hiện đại của mình trong các cửa sổ 64 bit của mình, tôi có thể nhận được hơn một nghìn (1000!) FPS, quá nhanh để mọi người chơi nếu xử lý vật lý "giả định" nó chạy trong khoảng 50-60 khung hình / giây.
Những gì các nhà phát triển ngày nay (có thể) làm là:
- Bật V-Sync trong trò chơi (* không khả dụng cho các ứng dụng có cửa sổ ** [aka chỉ khả dụng trong các ứng dụng toàn màn hình])
- Đo chênh lệch thời gian giữa lần cập nhật gần nhất và cập nhật vật lý theo chênh lệch thời gian giúp trò chơi / chương trình chạy hiệu quả ở cùng tốc độ bất kể tốc độ FPS
- Hạn chế tốc độ khung hình
*** tùy thuộc vào cấu hình card đồ họa / trình điều khiển / os có thể có thể.
Đối với điểm 1 không có ví dụ nào tôi sẽ trình bày vì nó không thực sự là bất kỳ "lập trình" nào. Nó chỉ sử dụng các tính năng đồ họa.
Đối với điểm 2 và 3, tôi sẽ hiển thị các đoạn mã và giải thích tương ứng:
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;
}
}
}
Ở đây bạn có thể thấy đầu vào của người dùng và vật lý có sự khác biệt về thời gian, nhưng bạn vẫn có thể nhận được hơn 1000 FPS trên màn hình vì vòng lặp đang chạy nhanh nhất có thể. Bởi vì công cụ vật lý biết thời gian trôi qua bao lâu, nên nó không phải phụ thuộc vào "không giả định" hay "tốc độ khung hình nhất định" nên trò chơi sẽ hoạt động với cùng tốc độ trên bất kỳ cpu nào.
3:
Những gì các nhà phát triển có thể làm để hạn chế tốc độ khung hình, ví dụ, 30 FPS thực sự không có gì khó hơn, chỉ cần xem:
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;
}
}
}
Điều xảy ra ở đây là chương trình đếm được bao nhiêu mili giây đã trôi qua, nếu đạt được một lượng nhất định (33 ms) thì nó sẽ vẽ lại màn hình trò chơi, áp dụng hiệu quả tốc độ khung hình gần ~ 30.
Ngoài ra, tùy thuộc vào nhà phát triển, anh ấy / cô ấy có thể chọn giới hạn TẤT CẢ xử lý ở mức 30 khung hình / giây với mã trên được sửa đổi đôi chút về điều này:
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;
}
}
}
}
Có một vài phương pháp khác, và một số trong số đó tôi thực sự ghét.
Ví dụ, sử dụng sleep(<amount of milliseconds>)
.
Tôi biết đây là một phương pháp để hạn chế tốc độ khung hình, nhưng điều gì xảy ra khi quá trình xử lý trò chơi của bạn mất 3 mili giây trở lên? Và sau đó bạn thực hiện giấc ngủ ...
điều này sẽ dẫn đến tốc độ khung hình thấp hơn so với cái mà chỉ sleep()
nên gây ra.
Ví dụ, hãy dành thời gian ngủ là 16 ms. điều này sẽ làm cho chương trình chạy ở 60 hz. bây giờ việc xử lý dữ liệu, đầu vào, bản vẽ và tất cả các công cụ mất 5 triệu giây. bây giờ chúng tôi đang ở mức 21 triệu giây cho một vòng lặp, kết quả là hơi thấp hơn 50 hz, trong khi bạn vẫn có thể dễ dàng ở mức 60 hz nhưng vì giấc ngủ không thể.
Một giải pháp sẽ là tạo một giấc ngủ thích ứng dưới dạng đo thời gian xử lý và trừ thời gian xử lý khỏi giấc ngủ mong muốn dẫn đến việc sửa "lỗi" của chúng tôi:
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);
}
}
}