Journeyman Geek'in (kodlamam reddedildi çünkü) kodlama bölümü / geliştirici bakış açısıyla ilgilenen insanlar için verdiği cevaba ek olarak:
Programcıların bakış açısından, ilgilenenler için, DOS zamanları, her CPU onayının önemli olduğu zamanlardı, böylece programcılar kodu olabildiğince hızlı tuttu.
Herhangi bir programın maksimum CPU hızında çalışacağı tipik bir senaryo bu basittir (sözde C):
int main()
{
while(true)
{
}
}
Bu sonsuza kadar sürecek, şimdi, bu kod parçacığını sözde DOS oyununa dönüştürelim:
int main()
{
bool GameRunning = true;
while(GameRunning)
{
ProcessUserMouseAndKeyboardInput();
ProcessGamePhysics();
DrawGameOnScreen();
//close game
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
Eğer DrawGameOnScreen
fonksiyonlar çift tamponlama / V-sync kullanmıyorsa (ki, DOS oyunlarının yapıldığı günlerde biraz pahalıydı), oyun maksimum CPU hızında çalışacaktır. Modern bir günde mobil i7 bu (saniyede yaklaşık 1.000.000 ila 5.000.000 kez çalışacaktı (dizüstü bilgisayar yapılandırmasına ve mevcut cpu kullanımına bağlı olarak).
Bu, 64bit pencerelerdeki modern CPU'mda çalışan herhangi bir DOS oyununu çalıştırabilirsem, fizik işlemeyi "varsa" yürütürse, herhangi bir insanın oynaması için çok hızlı olan binden fazla (1000!) FPS elde edebileceğim anlamına gelirdi. 50-60 fps arasında.
Günümüzdeki geliştiricilerin (yapabilecekleri) yapabilecekleri:
- Oyunda V-Sync'i etkinleştirin (* pencereli uygulamalar için mevcut değildir ** [aka sadece tam ekran uygulamalarda kullanılabilir])
- Son güncelleme arasındaki zaman farkını ölçün ve FPS oranına bakılmaksızın oyunu / programı etkin bir şekilde aynı hızda çalıştırmasını sağlayan zaman farkına göre fiziği güncelleyin
- Kare hızını programsal olarak sınırlayın
*** grafik kartına / sürücüye / os konfigürasyonuna bağlı olarak mümkün olabilir .
Nokta 1 için göstereceğim hiçbir örnek yok çünkü gerçekten herhangi bir "programlama" değil. Sadece grafik özelliklerini kullanıyor.
2. ve 3. noktalara gelince, karşılık gelen kod parçacıklarını ve açıklamalarını göstereceğim:
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;
}
}
}
Burada kullanıcı girişi ve fiziğin zaman farkını hesaba kattığını görebilirsiniz, ancak döngü mümkün olduğu kadar hızlı çalıştığı için hala ekranda 1000+ FPS elde edebilirsiniz. Fizik motoru ne kadar zaman geçtiğini bildiğinden, "varsayım yok" ya da "belirli bir kare hızına" bağlı olması gerekmez, böylece oyun herhangi bir cpu üzerinde aynı hızda çalışır.
3:
Geliştiricilerin kare hızını sınırlamak için yapabilecekleri, örneğin, 30 FPS aslında daha zor bir şey değil, sadece bir göz atın:
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;
}
}
}
Burada gerçekleşen, programın kaç milisaniyenin geçtiğini saymasıdır, eğer belirli bir miktara ulaşıldığında (33 msn) oyun ekranını yeniden çizer ve etkin bir şekilde ~ 30 civarında bir kare hızı uygular.
Ayrıca, geliştiriciye bağlı olarak, TÜM işlemeyi 30 fps ile sınırlamayı seçebilir, yukarıdaki kod bu şekilde hafifçe değiştirilir:
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;
}
}
}
}
Birkaç başka yöntem var ve bazıları gerçekten nefret ediyorum.
Örneğin, kullanarak sleep(<amount of milliseconds>)
.
Bunun kare hızını sınırlamanın bir yöntemi olduğunu biliyorum, ancak oyun işlemleriniz 3 milisaniye veya daha fazla sürdüğünde ne olur? Ve sonra sen uykuyu çalıştır.
bu, sadece sleep()
neden olması gerekenden daha düşük bir kare hızına neden olacaktır.
Örneğin, 16 ms'lik bir uyku süresi alalım. Bu, programı 60 hz'de çalıştırır. Şimdi verilerin işlenmesi, girdi, çizim ve tüm şeyler 5 milisaniye sürer. Şimdi bir döngü için 21 milisaniyeyiz, bu da 50 hz'den biraz daha az sonuç verirken, kolayca 60 hz'de olabilirsiniz ancak uykudan dolayı imkansız.
Çözümlerden biri , işlem zamanını ölçmek ve işlem zamanını istenen uykusundan düşmek şeklinde uyarlanabilir bir uyku yapmak olacaktır;
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);
}
}
}