Uyku kullanarak çizim / çizim kodundan tek bir iş parçacığında mantığı / güncellemeyi ayırma


9

Oyun nesnelerinin hızının FPS tarafından engellenmemesi gerektiğini, bunun yerine zamana dayalı olması gerektiğini okudum. Çizim hızını sınırlamadan performansı en üst düzeye çıkarmak ve zamana göre sabit bir mantık güncelleme hızı sağlamak için güncelleme / çizim kodunu nasıl ayırabilirim?

Mevcut sahte kodum aşağıdaki gibidir

loop
{
    draw();
    if (ticksElapsed() > 100)
    {
        update();
        ticks+= ticksElapsed();
    }        
}

Sorun, çizim kodunun update () hızının performansını engellemesidir. Ve% 100 cpu tüketir, çünkü uyku atılırsa, hem çizim / mantık işlevlerini atar.

Ayrıca SDL kullanıyorum ve bir vsync seçeneği yok gibi görünüyor. Ayrıca sabit ve değişken zaman adım terimleri duydum ama bu uyku ile nasıl yapılabilir emin değilim ()


1
Sadece beklemek için% 100 CPU gücü harcamanıza gerek yoktur, ticksElapsed () <100 ise döngülerin sonuna uyku (0) koyun. Başka bir iş parçacığı yoksa işletim sistemi hemen iş parçacığına geri döner. kaçmak istiyor. Ama artık% 100 CPU gücü israf etmiyor.
Maik Semder

Ancak, böyle bir 1 iş parçacığı kurulumu için en iyi çözüm vsync kullanmaktır, eğer vsync
yapamıyorsanız

Yanıtlar:


3

Kod snippet'inizde, çiziminiz ve güncellemeniz 15 ms'den (60 fps) daha az sürdüyse, oyununuzu meşgul bekleyerek sabit zamanlı adım modunda çalıştırmaya çalıştığınız anlaşılıyor. Bu mümkün ve bunun bir uyku çağrısı kullanılarak yapılamayacağını tahmin ettiniz, çünkü ne kadar uyuyacağınızı tam olarak bilmiyorsunuz. Meşgul bekleme döngüsü iyi bir çözümdür.

Ancak, güncelleme ve çiziminizin 15 ms'yi aştığı durumu düşünün, şimdi oyun çizimine ve güncellemenin yavaşlamasına sahipsiniz. Şimdi iki şeyden birini yapabilirsiniz: bu durumu algılayın ve kareleri bırakın (çizimi atlayın ve tekrar senkronize olana kadar doğrudan güncellemeye geçin) ancak bilgisayar sadece yavaşlarsa asla yakalanmaz.

Diğer bir çözüm, güncelleme mantığınızı sabit zamanlı bağımsız hale getirmektir. Bunun için ayrı bir ipliğe ihtiyacınız yok, sadece işlerin ne kadar hızlı hareket etmesi gerektiğine karar vermelisiniz. Kene başına 5 piksel yerine, saniyede 50 piksel kullanmalısınız. Bunu başarmak için yüksek hassasiyetli bir zamanlayıcı gerekir ve tüm güncelleme mantığınız son güncellemeden bu yana ne kadar zaman geçtiğini görmek için zamanlayıcıya erişebilmelidir.

Temel olarak şuradan gidersiniz:

void UpdatePlayer()
 player.x += 10;

için

void UpdatePlayer(float elapsedSeconds) //the total seconds elapsed since last update
 player.x += walkspeed * elapsedSeconds;

Yani motorum her zaman% 100 tüketecek ve bu konuda gerçekten yapabileceğim bir şey yok mu?
Oskenso Kashi

1
Programlayıcının almasına izin verdiği kadar döngü tüketir, ancak bu bir sorun değildir çünkü bir oyun oynarken çok fazla başka şey yapamazsınız :).
Roy T.

@Oskenso Ancak, 1'den fazla iş parçacığı kullanırsanız sorun olur, o zaman ana iş parçacığı diğerlerinin olabildiğince fazla çalışmasına izin vermez, while döngüsünde çok fazla hesaplama gücü harcar, gerçekten bir uyku düşünmelisiniz
Maik Semder

@Maik Semder: Uyku (x) 'nin doğru olmaması için bir çözümünüz var mı? Uyku aralığı geçtikten sonra, iplik çalışmaya hazırdır. Ancak hazır bir iş parçacığının hemen çalışması garanti edilmez. Bu zamanlayıcıya bağlı. İki iplik kullanırken başka çözümler de var, bunun için bu mükemmel makaleye bakın: altdevblogaday.com/2011/07/03/threading-and-your-game-loop
Roy T.

1
@Roy sleep (0) çözümdür. Çalıştırmak isteyen başka bir iş parçacığı yoksa ( Sleep WinAPI ) hemen döner ve diğer iş parçacıklarına çalışma şansı verir. Diğer iş parçacığı ana iş parçacığına karşılık olarak çalışma şansı vermezse, bir diş çekme probleminiz vardır, ancak ilk etapta uyku çağırmadan diğer her şeyi engellemek daha da kötü hale getirir ve neredeyse bir çözüm değildir. Anahtar, uyku (0) 'ı aramak ve hedef sabit kare hızınıza ulaşana kadar geçen süreyi test etmektir, böylece sadece beklemek için% 100 CPU harcamazsınız.
Maik Semder
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.