Java 2D oyun programlama: Bir oyun döngüsü yapmak için farklı yaklaşımlar


10

Java oyun programlamasında yeniyim, ancak ne kadar çok okursam, kafam karışıyor, çünkü bir oyun döngüsü yapmak için birkaç farklı yaklaşım gördüm: 1. Timer sınıfını kullanan standart yaklaşım (daha az gibi görünüyor) hassas). 2. System.nanoTime kullanan daha kesin yaklaşım. 3. scheduleAtFixedRate kullanan basit bir yaklaşım.

Genellikle hangisi tercih edilmelidir ve her bir yaklaşımın avantajları / dezavantajları nelerdir? Herhangi bir bilgi için şimdiden teşekkürler.

Yanıtlar:


7

Temel bir oyun döngüsü için, nanoTime () kullanarak zamanı alacağınız bir while döngüsü çalıştırırsınız, son kareden bu yana ne kadar zaman geçtiğini belirleyip oyun durumunuzu güncelleyip render edersiniz.

Http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime%28%29 kullanarak , geçen süre için anket yapabilirsiniz. Esasında ...

public static void main(String [ ] args)
{
    long current_frame_time = system.nanoTime();
    long last_frame_time = current_frame_time;

    while(gameIsRunning)
    {
        last_frame_time = current_frame_time;
        current_frame_time = system.nanoTime();

        long timeTaken = current_frame_time - last_frame_time;

        //update and render game here
    }
}

Bu temel yöntem, örneğin http://www.koonsolo.com/news/dewitters-gameloop/ ve http://gafferongames.com/game-physics/fix-your-timestep/ üzerinde geliştirilebilir .

Alternatif olarak, bir zamanlayıcı oluşturabilir ve bu zamanlayıcıyı güncellemenizi çalıştıracak ve her X milisaniyede bir oluşturacak şekilde ayarlayabilirsiniz. Ancak, böyle bir oyun döngüsü inşa etmenin bazı dezavantajları vardır.

Göre http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html : " Her Timer nesnesine karşılık gelen zamanlayıcı yılların tüm yürütmek için kullanılan tek bir arka plan iplik Zamanlayıcı görevlerinin hızlı bir şekilde tamamlanması gerekir Bir zamanlayıcı görevinin tamamlanması aşırı zaman alırsa, zamanlayıcının görev yürütme iş parçacığını "hog" eder. Bu da, daha sonraki görevlerin yürütülmesini geciktirebilir. rahatsız edici görev nihayet tamamlandığında (ve eğer) hızlı bir şekilde tekrarlayın. "

Göre http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html#scheduleAtFixedRate%28java.util.TimerTask,%20java.util.Date,%20long%29 : " Sabit oranlı yürütmede, her yürütme ilk yürütmenin zamanlanmış yürütme süresine göre zamanlanır. Bir yürütme herhangi bir nedenle (çöp toplama veya diğer arka plan etkinliği gibi) ertelenirse, hızlı bir şekilde art arda iki veya daha fazla yürütme gerçekleşir Uzun vadede, yürütme sıklığı, belirtilen dönemin tam tersi olacaktır (Object.wait (uzun) öğesinin altında yatan sistem saatinin doğru olduğu varsayılarak). "

Genellikle bir oyun döngüsünün ne kadar süreceğini önceden bilmediğinizden, oyun döngünüzü her X milisaniyede (hedef kare hızına bağlı olarak) yürütmek için bir zamanlayıcı ayarlamak, bir kare ne zaman çalıştırılacağı birkaç demetlenmiş kareye yol açabilir. bir çerçeve planlandığında yerine bitirildi. Bu olduğunda ... neden ilk olarak bir zamanlayıcı kullanıyorsunuz?

Şimdi, beni yanlış anlamayın, zamanlayıcı kötü bir sınıf değildir, ancak periyodik olarak veya belirli bir zamanda yapılması gereken küçük görevler için genellikle daha uygundur, örneğin bir posta istemcisi her 5 yılda bir yeni postaları kontrol etmek isteyebilir veya bir sayaç yarışın başlamasından önce geri sayım göstermesi için saniyede bir azaltılabilir.


Soru, oyun döngüleri hakkındaydı, bu yüzden awt / swing bilgisi konu dışı. Ancak bu, sorudaki ilgisiz ve kafa karıştırıcı bir çizgi nedeniyle bilginin alakalı görünüyordu, bu yüzden bunu kaldırdım.
jhocking

Cevabımı soruda yapılan değişiklikleri yansıtacak şekilde uyarladım.
Exilyth

7

Ben ana döngü bir zamanlayıcı koymak olmaz. Daha ziyade, her kareyi işleyen bir 'while' döngüsü yapacağım ve daha sonra son kare / son yinelemeden bu yana ne kadar zaman geçtiğini hesaplamak için bir çeşit zaman işleyişi işlevselliği (Java'da System.nanoTime gibi geliyor) kullanacağım. döngü.

Bazı diller burada istisnalardır (örn. JavaScript, ActionScript), çünkü bu diller, bağlanmak için kapalı ana döngüye sahip bir ortamda (örn. Tarayıcı, Flash Player) çalışır, ancak bu istisna Java için geçerli değildir.

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.