2D platformlar: fiziği neden kare hızına bağımlı kılıyor?


12

"Super Meat Boy" son zamanlarda PC için çıkan ve olağanüstü kontrol ve piksel mükemmel atlama gerektiren zor bir platform oyunudur. Oyundaki fizik kodu, 60 fps'ye kilitlenmiş kare hızına bağlıdır; Bu, bilgisayarınız oyunu tam hızda çalıştıramazsa, fizik deli olacak, (diğer şeylerin yanı sıra) karakterinizin daha yavaş çalışmasına ve yere düşmesine neden olur. Ayrıca, vsync kapalıysa, oyun son derece hızlı çalışır.

2D oyun programlamasında deneyimli olanlar, oyunun neden bu şekilde kodlandığını açıklamaya yardımcı olabilir mi? Sabit bir hızda çalışan bir fizik döngüsü daha iyi bir çözüm olmaz mı? (Aslında, oyunun bölümleri için bir fizik döngüsü kullanıldığını düşünüyorum, çünkü bazı varlıklar kare hızından bağımsız olarak normal hareket etmeye devam ediyor. Öte yandan karakteriniz tam olarak [fps / 60] kadar hızlı çalışıyor.)

Bu uygulama hakkında beni rahatsız eden şey, oyun motoru ve grafik oluşturma arasındaki, monitör, grafik kartı ve CPU gibi sisteme özgü şeylere bağlı soyutlama kaybıdır. Herhangi bir nedenle, bilgisayarınız vsync'i işleyemiyorsa veya oyunu tam olarak 60 fps'de çalıştıramazsa, muhteşem bir şekilde bozulur. Oluşturma adımı fizik hesaplamalarını neden herhangi bir şekilde etkilemeli? (Günümüzde çoğu oyun ya oyunu yavaşlatacak ya da kareleri atlayacak. Bu neden ve bu damarda kare hızı bağımlılığı olmadan bir patformer oluşturmak mümkün olabilir mi? Grafik işlemeyi motorun geri kalanından ayırırsanız mutlaka bir hassasiyet kaybı olur mu?

Teşekkür ederim ve sorunun kafa karıştırıcı olup olmadığı için üzgünüm.


Sorunuza teğet. İşte tam olarak açıkladığınız sorunları ve zaman aralıklarını ve kare hızlarını ele almanın "doğru" yolunu kapsayan harika bir makale. gafferongames.com/game-physics/fix-your-timestep
num1

Aslında bu şekilde yapmaları beni gerçekten şaşırttı. Sanırım, öncelikle kare hızının güvenilebileceği konsol için inşa edilmiş olması gerekir. Hayal kırıklığı!
Iain

Yanıtlar:


7

Neden?

Birkaç neden, seçiminizi yapın: Daha iyisini bilmiyorlardı. Daha hızlı ve kolay uygulanır. Daha çok oyuna odaklandılar ve çoğu durumda ortaya çıkamayan uç durumlarda daha az odaklandılar.

Neden olmadığını açıklamak için oldukça iyi bir iş yaptın. Eminim konuyu kapsayan birçok konu olduğunu fark ettiniz . Listelediklerimin ötesinde tatmin edici bir cevap bulacağınızdan emin değilim.


"Daha iyisini bilmiyorlardı" neden "Jack is a Fool" ile bu yaklaşımı kullandığımı anlatıyor. Ama - Son mantığımdan bu yana tüm mantığımla dt'yi çağırmaya çok güvendim. Ama - noktalarının koordinatlarını, yüzen suret hatalar zor, bazı garip yol açabilir
lochok

4

SMB aslında tüm Xbox360'larda 60 fps'de çalışabileceğini varsaymanın güvenli olduğu bir konsol oyunuydu (bazı PAL oyuncuları için belki 50 olabilir). Sabit bir zaman çizelgesinin varsayılması, kodu adil bir şekilde basitleştirir.

Bir çok şeyi değişken bir zaman çizelgesiyle ölçeklendirmek kolay olsa da - 'pos + = hız * timestep', hızlanmalarla ve hızlanma değişim oranlarıyla uğraşırken bunu doğru yapmak oldukça zorlaşır.

Oyunun oynanması ve renderleme teoride güzel bir çözümdür , ancak iyi bir şekilde uygulanması (iyi enterpolasyon ile) oldukça zordur ve işler kolayca dağınık olabilir. Bu tekniğin gerçek oyunlarda kullanılması oldukça nadirdir (bazı büyük oyunlar bunu yapıyor, özellikle RTS oyunları, ancak daha çok ağ oyunu senkronizasyonu için).

Sabit bir ekran çözünürlüğü ve sabit bir kare hızı tasarlarken, kaydırmayı daha pürüzsüz hale getirmek için yapabileceğiniz başka bir şey daha var. Oyunun kare başına piksel sayısının tam olarak kaydırılmasını sağlayabilirsiniz - kare başına kesirli sayıda piksel kaydırarak alabileceğiniz herhangi bir 'alt piksel yalpalamasından' kaçınabilirsiniz.


1

Açık çözüm paralel olarak çalışan 2 döngüye sahip olmaktır - saniyenin 1 / 60'ını oluşturmak ve oyun saniyenin 1 / 60'ını oluşturmak.

Ancak Flash'taki deneyimimle (Super Meat Boy'un yaratıldığından emin olduğum AS3), zamanlayıcı her zaman çok doğru değil. Doğruluk ayrıca çevreye de bağlıdır. Bağımsız flash oynatıcıda milisaniyenin altında bir çözünürlüğe sahip olabilir. Ancak bazı web tarayıcılarında çalıştırıldığında, doğruluk kare hızına dönüşür.

Dolayısıyla, oluşturma ve oyun mantık döngülerini ayırmanın en yakın yolu, tüm hareketlerin zamana dayalı olmasını sağlamaktır (ve her kareyi son kareden bu yana geçen süreye göre çalıştırmak). Bu, bazı daha karmaşık matematiği getirebilir (bir nesnenin hızını belirli aralıklarla eklemek yerine, yerçekiminin sürekli uygulanması gibi). Oyun bir saniye gecikebileceğinden ve oyuncunuz bir adımda 200 piksel hareket edeceğinden, çarpışma algılama ve tepki daha da karmaşık hale gelebilir. Programcı çerçeve tabanlı çarpışma tespiti yapıyordu (her bir zaman aralığında bir çarpışma olup olmadığını kontrol ediyorsa), zaman bazlı çarpışma tespitine de geçmek zorunda kalacaklardı. Doğal hissetmelerini isteselerdi, yukarıda açıklanan yerçekimi yöntemini kullanmak zorunda kalacaklardı, bu da nesne hareketinin bir eğri olmasına (bir çizginin aksine),


2
Orijinal Meat Boy bir Flash oyunuydu. Super Meat Boy bir C ++ oyunudur.
Archagon

0

2D PC oyunlarının artık 60 fps'de oynamasını istemenin çok fazla olduğunu düşünmüyorum. Çoğu 2D oyun bile şimdi donanım hızlandırılmıştır, bu yüzden kişisel olarak fps gereksinimi hakkında endişelenmeyeceğim.

Asıl soru, neden piksel tabanlı kullanmıyorsunuz, oyunlar hilelerle ve kısayollarla doludur.

Eğer fizik tabanlı bir oyun (belki kuş atma?) Yapıyorsanız cevap açık, ama bir süper mario klonu? zamana dayalı hareket biraz fazla olabilir.


Bunları 60 fps'de oynatmak zor değil, ancak 50Hz, 70-85Hz ve 120Hz doğal yenileme oranlarına sahip ekranlar hala kolayca bulunabiliyor.

0

Kullandıkları 2. fizikte garip davranışlardan kaçınmak için?

Dürüst olmak gerekirse sadece tahmin edebilirim. Bir açıklama deneyeceğim:

Oyunun merkezinde ana oyun döngüsü vardır. Temel olarak şöyle görünür:

while(gameRunning)
{
  updateGame(timestep);
  renderGame(timestep);
}

updateGame gameState'i günceller: oyuncu girişini kontrol eder, oyuncu girişini oyun dünyasına uygular ve fizik simülasyonunu vb. çalıştırır.

renderGame oyunu çizer ve canlandırır.

Bu, fizik güncellemesini oluşturmaya bağlar. Bunu çözmek istiyorsanız, iş parçacıklarını kullanmanız ve oluşturmanın ve gameUpdate iş parçacığının her bir veri erişimini, örneğin oynatıcı konumu gibi paylaşılan verilere uygun şekilde senkronize etmeniz gerekir. Bu yapılabilir.

Başka bir sorun, fizik simülasyonunun kararlı çalışması için sürekli bir zaman çizelgesi gerektirmesi olabilir. Bu süpermeatboyun hareketi nasıl hesapladığına bağlıdır (Yine sadece nasıl yaptıklarını tahmin edebiliriz;)).

Saf bir yaklaşım olurdu (ki benim oyunumda * iç çekiyorum *):

position=position+speed*timestep;
speed=speed+acceleration*timestep;

Buna Euler Entegrasyonu denir ve genellikle kötü bir fikir olarak kabul edilir. Eğer zaman testi sabit değilse, simülasyonu daha az kararlı hale getirecek hesaplama hataları meydana gelir. Nesne aşırı hızlarda hareket edebilir veya hepsi olmayabilir ya da ekran dışından duvarlardan uçabilir. Zaman çizelgesi sabit olsa bile Euler Integration küçük hesaplama hatalarına neden olur. RK4 gibi başka bir entegrasyon yöntemi kullanın veya bir fizik motoru kullanın.

Bunun dışında eğer zaman aralığı çok büyürse çarpışma tespiti yapmakta sorunlar olabilir. İki oyun Güncellemesi arasında çarpışmalar kontrol edilmediğinden, nesneler engellerden geçebilir.

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.