[Çözüldü] Kod Yorumlaması ile İlgili Yardım İstiyorum

Başlatan blacksnow, 28 Aralık 2014 - 13:22:21

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

blacksnow

Başlık saçma olmuş olabilir.Aklıma başka bir şey gelmedi.İnternette bulduğum bir yılan oyununda anlamadığım bir kod parçası (aslında bir sınıf) var.
Ekrandaki çizdirilme işlemlerini hesaplamak için yapılmamış.Çünkü o işlem başka bir sınıfın içinde yapılıyor.Aşağıda onuda veriyorum.
package org.psnbtech;

/**
* The {@code Clock} class is responsible for tracking the number of cycles
* that have elapsed over time.
* @author Brendan Jones
*
*/
public class Clock {

/**
* The number of milliseconds that make up one cycle.
*/
private float millisPerCycle;

/**
* The last time that the clock was updated (used for calculating the
* delta time).
*/
private long lastUpdate;

/**
* The number of cycles that have elapsed and have not yet been polled.
*/
private int elapsedCycles;

/**
* The amount of excess time towards the next elapsed cycle.
*/
private float excessCycles;

/**
* Whether or not the clock is paused.
*/
private boolean isPaused;

/**
* Creates a new clock and sets it's cycles-per-second.
* @param cyclesPerSecond The number of cycles that elapse per second.
*/
public Clock(float cyclesPerSecond) {
setCyclesPerSecond(cyclesPerSecond);
reset();
}

/**
* Sets the number of cycles that elapse per second.
* @param cyclesPerSecond The number of cycles per second.
*/
public void setCyclesPerSecond(float cyclesPerSecond) {
this.millisPerCycle = (1.0f / cyclesPerSecond) * 1000;
}

/**
* Resets the clock stats. Elapsed cycles and cycle excess will be reset
* to 0, the last update time will be reset to the current time, and the
* paused flag will be set to false.
*/
public void reset() {
this.elapsedCycles = 0;
this.excessCycles = 0.0f;
this.lastUpdate = getCurrentTime();
this.isPaused = false;
}

/**
* Updates the clock stats. The number of elapsed cycles, as well as the
* cycle excess will be calculated only if the clock is not paused. This
* method should be called every frame even when paused to prevent any
* nasty surprises with the delta time.
*/
public void update() {
//Get the current time and calculate the delta time.
long currUpdate = getCurrentTime();
float delta = (float)(currUpdate - lastUpdate) + excessCycles;

//Update the number of elapsed and excess ticks if we're not paused.
if(!isPaused) {
this.elapsedCycles += (int)Math.floor(delta / millisPerCycle);
this.excessCycles = delta % millisPerCycle;
}

//Set the last update time for the next update cycle.
this.lastUpdate = currUpdate;
}

/**
* Pauses or unpauses the clock. While paused, a clock will not update
* elapsed cycles or cycle excess, though the {@code update} method should
* still be called every frame to prevent issues.
* @param paused Whether or not to pause this clock.
*/
public void setPaused(boolean paused) {
this.isPaused = paused;
}

/**
* Checks to see if the clock is currently paused.
* @return Whether or not this clock is paused.
*/
public boolean isPaused() {
return isPaused;
}

/**
* Checks to see if a cycle has elapsed for this clock yet. If so,
* the number of elapsed cycles will be decremented by one.
* @return Whether or not a cycle has elapsed.
* @see peekElapsedCycle
*/
public boolean hasElapsedCycle() {
if(elapsedCycles > 0) {
this.elapsedCycles--;
return true;
}
return false;
}

/**
* Checks to see if a cycle has elapsed for this clock yet. Unlike
* {@code hasElapsedCycle}, the number of cycles will not be decremented
* if the number of elapsed cycles is greater than 0.
* @return Whether or not a cycle has elapsed.
* @see hasElapsedCycle
*/
public boolean peekElapsedCycle() {
return (elapsedCycles > 0);
}

/**
* Calculates the current time in milliseconds using the computer's high
* resolution clock. This is much more reliable than
* {@code System.getCurrentTimeMillis()}, and quicker than
* {@code System.nanoTime()}.
* @return The current time in milliseconds.
*/
private static final long getCurrentTime() {
return (System.nanoTime() / 1000000L);
}

}


İşte burada zaten çizdirilme için geçen süre delta-ya atılıp FRAME_TIME dan çıkartılıyor.O zaman yukarıdaki sınıf ne iş yapıyor.
private void startGame() {
/*
* Initialize everything we're going to be using.
*/
this.random = new Random();
this.snake = new LinkedList<>();
this.directions = new LinkedList<>();
this.logicTimer = new Clock(9.0f);
this.isNewGame = true;

//Set the timer to paused initially.
logicTimer.setPaused(true);

/*
* This is the game loop. It will update and render the game and will
* continue to run until the game window is closed.
*/
while(true) {
//Get the current frame's start time.
long start = System.nanoTime();

//Update the logic timer.
logicTimer.update();

/*
* If a cycle has elapsed on the logic timer, then update the game.
*/
if(logicTimer.hasElapsedCycle()) {
updateGame();
}

//Repaint the board and side panel with the new content.
board.repaint();
side.repaint();

/*
* Calculate the delta time between since the start of the frame
* and sleep for the excess time to cap the frame rate. While not
* incredibly accurate, it is sufficient for our purposes.
*/
long delta = (System.nanoTime() - start) / 1000000L;
if(delta < FRAME_TIME) {
try {
Thread.sleep(FRAME_TIME - delta);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}


Böyle parça parça anlamak zor olabilir.Projenin tamamını paylaşıyorum.

https://github.com/PSNB92/SnakeRemake/tree/master/src/org/psnbtech

Soru biraz zor ama yine de yardımlarınızı bekliyorum.


Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 28 Aralık 2014 - 15:06:18

Anladığım kadarıyla biraz anlatmak istiyorum.Belki böyle daha kolay çözeriz.

Şimdi oyun her 20 ms de bir repaint ediliyor.Fakat yılanın kontrolleri her 20 ms de bir kontrol edilmiyor.Şöyle bir hesap yapılıyor clock sınıfında,
this.millisPerCycle = (1.0f / cyclesPerSecond) * 1000;
//Burada cyclesPerSecond 9.0f olarak giriliyor.


Ve burdan çıkan değere göre ( (1.0f / 9.0f) * 1000 = 111.1 ms) yılanın kontrolleri yapılıyor.Yani her 20 ms bir repaint yapılıyor ve her 111.1 ms bir yılanın çarpışmaları kontrol ediliyor.

Neden böyle bir şeye gerek duyuluyor.Yani her 100 ms de bir hem repaint yapılsa hem de yılanın kontrolleri yapılsa olmaz mı? Asıl sormak istediğim buydu.

rutku

Bunu debug modunda irdelemelisin. Çünkü programlama diliyle alakalı bir konu değil. Takıldığın yerde kodu düşündüğün şekilde düzeltip programın nasıl davrandığına bakmalısın. Yada yazan kişiyle iletişime geç.
Hayallerini kodla ...

uKiriş
Mezgeldek

blacksnow

@rutku kodu aslında biraz debug ettim.Sorunun altında buna göre bir sonuç çıkardım.Bu sonuca göre yardım edebilir misin?İngilizcem yeterli olmadığı için oyunu yapan kişiyle iletişime geçmem mantıklı gelmiyor.Teşekkürler.

rutku

Maalesef hiç vaktim yok. Google translate den basit cümeleler kurarak derdini anlatabilirsin. Ayrıca debugtan çözülebilecek bir konu bu.
Hayallerini kodla ...

uKiriş
Mezgeldek

Reverser

Alıntı yapılan: blacksnow - 28 Aralık 2014 - 13:22:21
Neden böyle bir şeye gerek duyuluyor.Yani her 100 ms de bir hem repaint yapılsa hem de yılanın kontrolleri yapılsa olmaz mı? Asıl sormak istediğim buydu.

Bu sorunun onlarca cevabı olabilir algoritma tam olarak kurulamamış olabilir, uygulama yazılma aşamasındayken değişikliğe uğramış olabilir v.b en iyisi uygulamayı yazan kişiye sormak bence de

XFCE ROCKS !
Powered by Thunar & XFWM4



blacksnow


Amenofis

Oyun motoru kullanılmadığı için bu denli ayrıntılı zamanlama hesapları gerekiyor olabilir. Sonuçta oyunlarda farklı hızlarda hareket eden nesneler var ve herbiri için farklı zamanlama gerekir. Normalde oyun motorları halleder öyle işleri.

Cycle dediği muhtemelen yılanın bir adımıdır. Yılan gitgide hızlandığı için cycle süresi de düşecek. Bunu düz mantıkla kare/sn ye oranlarsan kare/sn de gittikçe hızlanacak. Her karede girişleri okursa tepki süresi de buna paralel hızlanmaya başlayacak ve oyunu kontrol edemez duruma geleceksin. Bunu önlemenin yolu yılanın hızı ne olursa olsun klavye giriş periyodunu sabit tutmaktır.

blacksnow

Yılan gitgide hızlandığı için demişsiniz.Yılan neden hızlanıyor ki hız hep sabit değil mi? Açıkcası yazdıklarınızı 10 defadan fazla okudum.Anlayamadım.Eğer vaktinizi almıyorsam sayılarla bir örnek verebilir misiniz? Tekrardan teşekkürler.

Amenofis

Özür dilerim aklım başka yere gittiği için biraz karıştırmışım. Demek istediğim kısaca şu;

Her 100ms de bir repaint ve yön kontrolü yaparsan oyun hızı sürekli aynı kalır. Zorluk seviyesi ekleme istediğini düşün. En kolay modda yılan saniyede 5 adım, en zorda 50 adım ilerleyecek. Bunu sağlamak için fps yi 50 ye ayarlayıp zorluk seviyesine göre kare atlama (frame skip) yapacaksın. En zor modda 0, en kolayda 45 atlama. Tabi bunu zamanı eşit şekilde bölerek yapmalısın. Önce 45 kareyi birden atlayıp sonra beşini birden çizersen olmaz tabi.

blacksnow

Eğer 5 adım olursa 200 ms de bir hareket edecek, 50 adım olursa 20 ms de bir hareket edecek.Bu sayade de saniyede gösterilen kare sayısı sabit kalacak ama yılan hızlanıp yavaşlayabilecek.

Peki saniyede gösterilen kare sayısının sabitlenmek istenmesinin sebebi nedir? Sabitlenmezse ne gibi sakıncaları olur? Yani görsel olarak ne farkeder?

Çünkü bende bu oyuna bakarak bir yılan oyunu yapmıştım ve bir clock sınıfı yapmamıştım.Sadece değeri yazıyordum 100 ms, 50 ms gibi ve buna göre hızlandırıp yavaşlatıyordum.

Şöyle bir baktımda çok soru soruyorum galiba.Umarım başınızı ağrıtmıyorumdur.

Amenofis

Görsel olarak bişey farketmez. Anahtar kelime esneklik.

Hiçbir oyunda kare/sn oyundaki objeye göre uydurulmaz, objelerin hareketleri kare/sn ye göre hesaplanır. Ha diyebilirsin bu basit bir oyun, zaten tek obje var ne fark eder? Seçim senin ama bir yazılımın temelini atarken sonraki muhtemel değişikliklere, eklemelere kolay adapte olabilmesi için mümkün olduğunda esnek olması beklenir.

Bence üşenme sen de benzer bir zamanlayıcı sınıf geliştir. Atıyorum her obje bu sınıfı devralsın ve hareketlerini kolayca zamanlayabilsin. İlkel bir obje sınıfı da olabilir.

class GameObject {
abstract .... metod(...);
...
}
class Snake extends GameObject {
...
}

Bunu nasıl yapacağını bana sorma ama. Ben oyun geliştirme konusunda tecrübeli değilim. Sadece basit teorik bilgileri aktarıyorum. Bunlar da zaten en temel şeyler.

blacksnow

Temel olarak mantığı kavradım.Ben de bir clock sınıfı yazıp daha iyi anlamaya çalışıcam.Benim için önemli bilgilerdi çok teşekkürler @Amenofis