получение странных результатов из кода с частотой кадров
-
12-09-2019 - |
Вопрос
Я пытаюсь поддерживать скорость моей игры 60 кадров в секунду, но я получаю странные результаты из своего кода, например "2-8000 кадров в секунду", Почему это не остается на уровне 60?
public static void main(String[] args) {
joglplat m = new joglplat();
while(true){
long startTime = System.nanoTime() / 1000000;
try
{
// 123456: 6 zeros => 16ms
long nsToSleep = 16000000 - (System.nanoTime() - lastFrame);
System.out.println("ns: " + nsToSleep);
lastFrame = System.nanoTime();
if(nsToSleep > 0)
{
System.out.println("ns2: " + (nsToSleep/1000));
System.out.println("ns3: " + (nsToSleep%1000));
Thread.sleep(nsToSleep/16000000, (int)(nsToSleep % 1000));
}
else
{
Thread.yield(); // Only necessary if you want to guarantee that
// the thread yields the CPU between every frame
}
}
catch(Exception e){
e.printStackTrace();
}
m.controls();
m.update();
m.repaint();
System.out.println("framerate: " + (System.nanoTime() / 1000000 - startTime));
}
}
Решение
Ваш результат — это количество секунд, в течение которых работала ваша программа, а не частота кадров.Вам следует разделить количество кадров (которое вы не собираете) на общее время работы.
Чтобы получить количество кадров, просто добавьте новую переменную вне игрового цикла и увеличивайте ее каждый раз...
public static void main(String[] args) {
long frames = 0;
joglplat m = new joglplat();
while(true){
frames++;
// other code here
System.out.println("framerate: " + ((System.nanoTime() / 1000000 - startTime) / frames ) );
}
}
Однако учтите, что это даст вам среднюю частоту кадров на протяжении всего выполнения вашей программы.Два других варианта — получить мгновенную частоту кадров и среднюю частоту кадров за последние N кадров.
Все стили в одном (непроверенные/нескомпилированные, поэтому могут быть некоторые ошибки, но это поможет вам начать в правильном направлении):
public static void main(String[] args) {
long startTime = System.nanoTime();
long lastFrameTime = startTime;
long frames = 0;
int framesToAverage = 10;
long[] frameTimes = new long[framesToAverage];
joglplat m = new joglplat();
while(true){
// logic here
long currentFrameDuration = System.nanoTime() - lastFrame;
lastFrameTime = System.nanoTime();
long instantFramerate = currentFrameDuration / 1000000;
int currentFrameIndex = frames % frameTimes.length;
frameTimes[currentFrameIndex] = currentFrameDuration;
frames++;
long averageFramerate = ( ( lastFrameTime - startTime) / frames ) / 1000000;
long instantFramerate = currentFrameDuration / 1000000;
if( frames > frameTimes.length ) { // if it isn't, we don't have enough data yet
int firstFrameIndex = currentFrameIndex + 1;
if( firstFrameIndex > frameTimes.length ) {
firstFrameIndex = 0;
}
long averageFrameratePerN = ( ( frameTimes[currentFrameIndex] - frameTimes[firstFrameindex] ) / frameTimes.length ) / 1000000;
}
// yield/sleep here
}
}
Другие советы
Я подозреваю, что это вызвано неточностью Thread.sleep():
Переводит текущий выполняющийся поток в спящий режим (прекращает выполнение) на указанное количество миллисекунд плюс указанное количество наносекунд, при условии соблюдения точности системных таймеров и планировщиков. Поток не теряет права собственности ни на какие мониторы.
Есть ли какая-то причина, по которой вы должны вот так снижать частоту кадров?Возможно, вы могли бы более подробно объяснить, чего вы пытаетесь достичь?