2014-11-08 3 views
1

Я пытаюсь написать свой собственный игровой цикл. Но использование процессора слишком велико. Это около 25%. Моя проблема может быть в том, что нет Thread.sleep. Но я не хочу использовать это, он должен быть не очень точным. Также для вычисления следующего кадра понадобится 10 мс.Java: игровой цикл - загрузка процессора слишком высока

Мой код делает это:
1: перекрашивать окно («Fenster» это окно на немецком языке)
2: зачитать миллисекунды
3: установить следующий кадр
Я хочу иметь 50 кадров в секунду , Таким образом, программе нужно ждать 1000/50 = 20 мс каждый кадр.
4: Вычислить разность времени и после создания следующего кадра

 // GameSchleife 
     while (true) { 

      // First repaint 
      fenster.repaint(); 

      // Before calculating the next frame, capture the time 
      long a = System.currentTimeMillis(); 
      long b = a; 

      // Calculate the next frame 
      fenster.Update(); 

      // Wait for 20 ms (50 frames in a second) 
      for (int time = 0; time < 20;) { 

       // Wait for at least 1 ms 
       while (a == b) { 
        a = System.currentTimeMillis(); 
       } 

       // Difference from a and b 
       time = time + ((int) (a - b)); 

       // 
       a = System.currentTimeMillis(); 
       b = a; 

      } 
     } 
+0

Так каково ваше вопрос? –

ответ

4

Почему бы Thread.sleep быть менее точным, чем ваш код? Вы протестировали его и нашли его неточным? Если вы не хотите спать в течение 20 мс, разделите сон на несколько частей, отрегулировав окончательный сон, чтобы общее количество составляло 20 мс.

Что-то вроде этого: (я C# DEV, так что вы, возможно, придется подстраивать код немного)

while (true) 
{ 
    long startTime = System.currentTimeMillis(); 

    fenster.repaint(); 

    long remaining= 20 - (System.currentTimeMillis() - startTime); 
    Thread.sleep(remaining - 2); // adds up to 18 ms since start if repaint took 10ms 

    remaining= 20 - (System.currentTimeMillis() - startTime); 
    Thread.sleep(remaining); // should be 1-2ms 
} 

код у вас есть теперь убить любой аккумулятор для ноутбука в кратчайшие сроки, и это возможно отдавания другие проблемы с нагревом.

Редактировать: Добавлен fenster.repaint(). Также исправлен код, чтобы repaint + wait составлял 20 мс. Этот код сломается, если repaint занимает больше 18 мс, поэтому добавьте несколько тестов.

Другое редактирование, чтобы уточнить: Ваша рамка занимает 10ms для рисования. Чтобы достичь 50 кадров в секунду, у вас в общей сложности 20 мс на кадр, т. Е. Если перерисовка заняла 11 мс, вы должны спать 9 мс, прежде чем рисовать следующий кадр.

firstTime назначается первым, за которым следует repaint, которые принимают appx 10ms. После перекраски мы снова проверим системный таймер и вычтем время начала, чтобы получить прошедшее время. Затем мы вычитаем это число из 20, чтобы получить количество мс до следующей перерисовки.

Затем мы вводим сон, но вычитаем 2 мс, чтобы иметь небольшой запас, если системный таймер является неточным. Снова пересчитаем оставшееся время (1-2 мс) и введите еще один короткий сон.

Все это добавляет до 20 мс, и вы можете отобразить следующий кадр.

+0

Хм ... Я не понимаю ваш код? Почему бы не потрогать (20) в начале? Я не тестировал его. – LittleSatan

+0

Просто добавил дополнительный код, помог ли он? – EventHorizon

+0

О, да, это работает: 3, но я добавил if (осталось> = 2) { Thread.sleep (осталось - 2); }, поэтому он не будет разбит. – LittleSatan

0

Так много вложенных циклов влияет на производительность

while (true) { 
... 

// Wait for 20 ms (50 frames in a second) 
for (int time = 0; time < 20;) { 

// Wait for at least 1 ms 
while (a == b) { 

... 

вы должны проверить различия каждый 20мс, и попытаться исправить ошибку каждый второй или так ... что-то вроде:

while (true) { 
    if (((int) System.currentTimeMillis() % 20) == 0) { 
     fenster.repaint(); 
     // Calculate the next frame 
     fenster.Update(); 
    } 
} 
Смежные вопросы